Commit graph

200 commits

Author SHA1 Message Date
Romain Bazile f1b49e672b main.json: update to update code ;-) 2020-11-27 11:53:21 +01:00
Romain Bazile 4f5c59c061 imager: remove minimum volume check (done in Node-Red now) 2020-11-27 11:31:18 +01:00
Romain Bazile bcb1e245f0 usb_backup: fix typo and add purge of files 2020-11-27 11:30:49 +01:00
Romain Bazile a62891eb6a light: catch exceptions 2020-11-27 11:30:29 +01:00
Romain Bazile 1cf3d1df12 Fix bugs all around 2020-11-25 17:01:14 +01:00
Romain Bazile 05dc317095 imager: add support for white balance 2020-11-24 17:31:11 +01:00
Romain Bazile 3bb27b9e15 integrity: this and udev rule closes #15 2020-11-20 18:03:55 +01:00
Romain Bazile 6009e07cd6 first release of the integrity check mechanism 2020-11-20 18:03:55 +01:00
Romain Bazile ae29f8597e Main: print the machine name 2020-11-16 17:53:23 +01:00
Romain Bazile f27c9823a1 Integration of raspimjpeg
The source code of the modified version of raspimjpeg used by the PlanktoScope is hosted [here](https://github.com/PlanktonPlanet/userland/tree/master/host_applications/linux/apps/raspicam).

We moved away from picamera to improve the stability of the system. This commit should closes the elusive #51 and #54.

After a lot of tests, it was clear that even a forked version of picamera was not going to solve our problem while also improving on our capturing speed.

The modified version of RaspiMJPEG does that.
RaspiMJPEG streams the image flux to /dev/shm/mjpeg/cam.jpg . This is passively reloaded by the streaming server (still written in python).

RaspiMJPEG is controlled through a special file called a Pipe which is used to send it commands.
The list is available [here](https://github.com/PlanktonPlanet/userland/tree/master/host_applications/linux/apps/raspicam/Config.md).

The raspimjpeg binary is distributed directly in this repository, in the folder `scripts/raspimjpeg/bin/`.
2020-11-16 17:53:23 +01:00
Romain Bazile fcb57ed075 segmenter: import libraries when needed to make startup faster 2020-11-16 17:53:23 +01:00
Romain Bazile 98c51828e0 stepper: reduce method size 2020-11-16 17:53:23 +01:00
Romain Bazile 12712c241e imager: reduce methods size 2020-11-16 17:53:23 +01:00
Romain Bazile 4bcc9f1153 switch off bandit error that are not pertinent 2020-11-14 09:45:14 +01:00
Romain Bazile 736a09ff5f imager: catch BrokenPipeError 2020-11-14 09:45:14 +01:00
Romain Bazile 83f45d6c2f add microstep configuration option 2020-11-14 09:45:14 +01:00
Romain Bazile b66776a5fb sourcery.ai cleanup 2020-11-14 09:45:14 +01:00
Romain Bazile a5a76979b9 addition of uuidname module 2020-11-14 09:45:14 +01:00
Romain Bazile 1530c71fb0 Python: add/remove todos 2020-10-21 21:25:59 +02:00
Romain Bazile 06d9facb3d segmenter: fix morphocut error with objects files in img folder 2020-10-21 21:25:59 +02:00
Romain Bazile 3ce7f6aa5e stepper: fix pump bug where it doesn't stop 2020-10-21 21:25:59 +02:00
Romain Bazile 2cf0ff8341 main.py: change default log rotation/retention settings 2020-10-21 21:25:59 +02:00
Romain Bazile e7ea63a43a Scripts README 2020-10-07 12:25:50 +02:00
Romain Bazile 140a3cf0de License! Martyr proposal 2020-10-07 12:25:50 +02:00
Romain Bazile e89cbdc2aa python: reminder to add tests 2020-10-07 12:22:52 +02:00
Romain Bazile 1a42f05941 python: improve log messages 2020-10-07 12:22:52 +02:00
Romain Bazile 2c9a6df20f segmenter: try to add support for printing object_id 2020-10-07 12:22:52 +02:00
Romain Bazile 20e07a110d stepper: add support for waveshare hat, for #11 2020-10-07 12:22:52 +02:00
Romain Bazile 1488459954 Change default img and export directories, closes #55 2020-10-07 12:22:52 +02:00
Romain Bazile a35b70e0fb segmenter: bugfixes 2020-10-07 12:22:52 +02:00
Romain Bazile fbacf21016 segmenter: typo fix in mqtt topic 2020-09-28 21:40:13 +02:00
Romain Bazile 06ef401a3b
Extraction and refactor of the python code from node-red flow
The rationale for this rewrite is to improve the readability, the modularity, the reliability and the future-proofing of the main python script.

All in all, this is now 124 commits that are going to be squashed and merged together, spanning more than two weeks of development and testing.

Please test away this release and break things. An upgrading guide will be published in the coming days, along with a new image for people to use if they don't want to upgrade on their own.

Read along if you want to know all the goodies!

As a starter, the python script was extracted from the main flow, and now lives in its own files at `PlantonScope/scripts/*`.

We set up the auto formatting of the code by using [Black](https://github.com/psf/black). This make the code clearer and uniform. We are using the default settings, so if you just install Black and set your editor to format on save using it, you should be good to go.

The code is separated in four main processes, each with a specific set of responsibilities:
- The main process controls all the others, starts everything up and cleans up on shutdown
- The stepper process manages the stepper movements. It's now possible to have simultaneous movements of both motors (this closes #38 ).
- The imager process controls the camera and the streaming server via a state machine.
- The segmenter process manages the segmentation and its outputs. The segmentation happens recursively in all folders in `/home/pi/PlanktonScope/img/`. Each folder has its own output archive, and bug #26 is now closed.


Those processes communicates together using MQTT and json messages. Each message is adressed to one topic. The high level topic controls which process receives the message. The details of each topic is at the end of this commit message.

Every imaging sessions has now its own folder, under the `img` root. Metadata are saved individually for every session, in a JSON file in the same directory as the pictures.

The configuration is not parsed from `config.json` anymore and passed directly through MQTT messages to the concerned process.

A new configuration file has been created: `hardware.json`. This file contains information related to your specific hardware configuration. You can choose to reverse the connection of the motors for example, but you can also define specific speed limits and steps number for your pump and focus stage. This will make it easier for people who wants to experiment with different kind of hardware. It's not necessary to have this file though. If it doesn't exists, the default configuration will be applied.

The code is architectured around 6 modules and about 10 classes. I encourage you to have a look at the files, they're pretty straightforward to understand.

There is a lot of work left around the node-red code refactoring, dashboard ui improvements, better and clearer LED messages, OLED screen integration and finer control of the segmentation process, but this is quite good for now.


Here is the topic lists for MQTT and the corresponding messages.
- actuator :  This topic adresses the stepper control thread
              No publication under this topic should happen from the python process
  - actuator/pump :   Control of the pump
                      The message is a json object
                      {"action":"move", "direction":"FORWARD", "volume":10, "flowrate":1}
                      to move 10mL forward at 1mL/min
                      action can be "move" or "stop"
                      Receive only
  - actuator/focus :  Control of the focus stage
                      The message is a json object, speed is optional
                      {"action":"move", "direction":"UP", "distance":0.26, "speed":1}
                      to move up 10mm
                      action can be "move" or "stop"
                      Receive only
- imager/image :      This topic adresses the imaging thread
                      Is a json object with
                      {"action":"image","sleep":5,"volume":1,"nb_frame":200}
                      sleep in seconds, volume in mL
                      Can also receive a config update message:
                      {"action":"config","config":[...]}
                      Can also receive a camera settings message:
                      {"action":"settings","iso":100,"shutter_speed":40}
                      Receive only
- segmenter/segment : This topic adresses the segmenter process
                      Is a json object with
                      {"action":"segment"}
                      Receive only
- status :    This topics sends feedback to Node-Red
              No publication or receive at this level
  - status/pump :     State of the pump
                      Is a json object with
                      {"status":"Start", "time_left":25}
                      Status is one of Started, Ready, Done, Interrupted
                      Publish only
  - status/focus :    State of the focus stage
                      Is a json object with
                      {"status":"Start", "time_left":25}
                      Status is one of Started, Ready, Done, Interrupted
                      Publish only
  - status/imager :   State of the imager
                      Is a json object with
                      {"status":"Start", "time_left":25}
                      Status is one of Started, Ready, Completed or 12_11_15_0.1.jpg has been imaged.
                      Publish only
  - status/segmenter :   Status of the segmentation
      - status/segmenter/name
      - status/segmenter/object_id
      - status/segmenter/metric




Here is the original commit history:
* Extract python main.py from flow

* Fix bug in server addresses

These addresses should be the loopback device instead of the network 
address of the device. Using the loopback address will not necessitate 
to update the script when the network address changes.

* clean up picamera import

* changes to main python and flow:
update MQTT requests address to localhost (bugfix)
update streaming output address to nothing
update main flow to remove python script references and location

* Automatically initialise imaging led on startup to off state.

* Add the ability to invert outputs of the motor

We added a key to config.json "hardware_config" with a subkey 
"stepper_reverse". If this key is present in the config file and set to 
1, the output of the motors are inversed (stepper2 becomes the pump 
motor and stepper1 the focus motor)

* move all non main script to a subfolder

* add __init__.py to package

* light module rewrite

* json cleanup and absolute path for config file

* light.py forgot to import subprocess

#oups

* Add command to turn the leds off

* Auto formatting of main.py

I've used Black with default settings, see https://github.com/psf/black

* First commit of stepper.py
Pump parameters still needs to be checked and tuned.

* addition of hardware details in config.json

* Introduce hardware.json to replace the `hardware_config` of config.json

* stepper.py: calibration, typos

* creates the MQTT_Client class

* pump_max_speed is now in ml/min to help readability

* forgot to add self to the class def

* addition of threading capabilities to stepper.py (UNTESTED)

* mqtt: fix topic bug

* remove counter

* mqtt add doc about topics

* stepper.py creates an "actuator/*/state" topic

* stepper.py: rename mqtt_client to pump_client

* mqtt.py: add details about topics

* stepper.py: rename pump_client to actuator_client

* topic was not split properly and a part was lost

* switch to f-strings for mqtt.py

* cosmetic update

* stepper.py: folder name will be planktoscope change calls

* hardware.json became more straightforward

* stepper.py syntax bugs

* stepper.py addition of a received stop command

* stepper.py: update to max travel distance

* stepper.py: several typos here

* rename folder

* main.py: reword to reflect folder rename

* main.py: remove logic that has been moved to stepper.py and mqtt.py

* main.py: update to add mqtt imaging client

* mqtt.py: make command and args local to class and output more verbose

* make stepper.py a class

* main.py: instantiate stepper class and call it

* main.py: name mqtt client

* update to main.json to reflect main.py changes

* fix bugs around pump control

* update flows to latest version from Thibault

* distance can be a small value, and definitevely should be a float.

* unify mqtt topics

* unify mqtt output in the main flow

* first logger implementation, uses loguru

* mqtt: add reason to on_connect

* mqtt: add on_disconnect handler

* stepper: add more logger calls for debug mainly

* main: add levels for logger

* imager.py: first move of the imager logic

* imager: time import cleanup

* imager: morphocut import cleanup

* imager: skimage import cleanup

* imager: finishing import cleanup

* imager: Class creation - WIP

Also provides a fix for #26 (see line 190).

* imager: threading is needed for Condition()

* streamer: get the streamer server its own file

* imager: creates start_camera and get the server creation out

* imager: subclass multiprocessing.Process

* imager: get Pipeline creation its own function

* imager: cleanup of self calls

* main: code removal and corresponding calls to newly created classes

* imager: various formatting changes

* main: management of signal shutdown

* add requirements.txt

* mqtt: messages are now json objects

Also, addition of a flag on receiving a new message

* mqtt: make message private and add logic to synchronise

* stepper: creates the stepper class

* stepper: use the new class

* stepper: uses the new logic

* stepper: add the shutdown event

* stepper: add shutdown method

* main: add shutdown event

* imager: graceful shutdown

* stepper: nicer way of checking the Eevnt

* self is a required first argument for a method in a class

Especially if you use said class private members!

* python: various typos and small errors in import

* stepper: create mqtt client during init

* stepper: instanciate the mqtt client inside run

Otherwise it's not accessible from inside the loop. It's a PITA,
more information at  https://stackoverflow.com/questions/17172878/using-pythons-multiprocessing-process-class

* stepper: little bugs and typos all around

* mqtt: add shutdown method

* mqtt: add connect in init

* stepper: fix bugs, sanitize inputs

* stepper: work on delay prediction improvements

* stepper: json is mean, double quote are mandatory inside

* mqtt: add details about message exchanged

* imager: first implementation of json messages

* main.json: add new tab for RPi management + json for payloads

* imager: add state_machine class

* stepper: publish last will

* imager: major refactor

* main: make streaming server process a daemon

* mqtt: insert debug statement on close

* main: reorder imports

* imager: make it work!

Reinsert the streaming server logic in there, because there is a problem with the synchronisation part otherwise.
Also, eventually, StreamingOuput() will have to be made not global

Final very critical learning: it's super duper important to make sure the memory split is at least 256Meg for the GPU.
Chaos ensues otherwise

* main: changes to accomodate the streamer/imager fusino

* imager_state_machine: insert states transition description

* stepper: cleanup of code

* segmenter: creation of the class

* python: include segmenter changes

* remove unused files

* stepper: check existence of hardware.json

* main.json: changes to reflect the python script evolution

* remove unecessary TODOs and add some others

* main: add check for config and directories

* imager: update_config is implemented and we have better management of directories now

* segmenter: now work recursively in all folders

* flow: the configuration is now sent via mqtt

* segmenter: better manage pipeline error

* segmenter: declaration of archive_fn in init

* imager: small bugs and typos

* main: add uniqueID output

* imager: add the camera settings message

We can now update the ISO, shutter speed and resolution from Node-Red

* package.json: update dependencies
2020-09-28 11:05:27 +02:00
tpollina 5007ba35b5
Delete mqtt_pump_focus_image_segment_strem.py 2020-07-25 11:20:33 +02:00
tpollina 961146adbc
Delete mqtt_pump_focus_image.py 2020-07-25 11:20:25 +02:00
tpollina c474b3a7e6
Delete Morphocut_segmentation.py 2020-07-14 16:56:17 +02:00
tpollina 889d2eedae
Delete StackFlow_v3.py 2020-07-14 16:56:04 +02:00
thibaut pollina a80fae1af5 update README.md 2020-02-09 00:20:14 -08:00
thibaut pollina 60bdc3ede6 Clean up useless files 2020-02-09 00:15:36 -08:00
tpollina ff12a2e4e4
Create mqtt_pump_focus_image_segment_strem.py 2020-02-04 21:00:12 -08:00
tpollina ba0cf44e74
Update mqtt_nodered.json 2020-02-04 20:59:16 -08:00
tpollina 29183d9fb1
Update mqtt_nodered.json 2020-02-04 08:08:30 +01:00
tpollina 86e783ceee
Create mqtt_pump_focus_image_v2.py 2020-02-04 08:07:58 +01:00
tpollina 9f1609ded4
Update mqtt_pump_focus_image.py 2020-02-02 04:20:55 +01:00
tpollina 78de7302ad
Update mqtt_pump_focus_image.py 2020-02-01 21:25:49 +01:00
tpollina af90680da7
Update mqtt_pump_focus_image.py 2020-01-31 08:49:32 +01:00
tpollina b0353fc63b
Create mqtt_nodered.json 2020-01-30 19:44:27 -08:00
tpollina 58fa23b0eb
Create mqtt_pump_focus_image.py 2020-01-30 19:42:39 -08:00
tpollina cfeccf3faa
Create Morphocut_segmentation.py 2020-01-30 17:53:37 +01:00
tpollina b67f62746f
Create StackFlow_v3.py 2020-01-30 17:52:00 +01:00
tpollina 945d3a65fc
Rename scripts/flows.json to flows/flows.json 2020-01-27 16:29:58 -08:00
tpollina dca9e1f600
Rename scripts/flows_planktonscope.json to flows/flows_planktonscope.json 2020-01-27 16:29:38 -08:00
tpollina 3c3b281be2
Rename scripts/flow_villefranche.json to flows/flow_villefranche.json 2020-01-27 16:29:17 -08:00
tpollina 934c5cfeb8
Add files via upload 2020-01-27 14:40:43 -08:00
tpollina f9927cd90d
Create flow_villefranche.json 2020-01-27 19:10:43 +01:00
tpollina b45e0babfe
Update focus.py 2020-01-15 15:46:19 +01:00
tpollina 22045c9e8e
Delete recover.py 2020-01-15 15:45:11 +01:00
tpollina d129734d62
Add files via upload 2020-01-08 14:32:46 +01:00
tpollina 1f46ea7e07
Update focus.py 2019-12-19 04:57:32 -08:00
tpollina 3e796d83bb
Rename scripts/install.rst to docs/install.rst 2019-12-16 19:10:02 -08:00
tpollina 469a7bca03
Rename install.rst to scripts/install.rst 2019-12-16 19:09:49 -08:00
tpollina 75f6770645
Update flows_planktonscope.json 2019-12-15 01:04:37 -08:00
tpollina 7430a9e295
Update flows_planktonscope.json 2019-12-14 20:52:33 -08:00
tpollina 5ebdee94d7
Add files via upload 2019-12-14 20:40:50 -08:00
tpollina fd3ebd1ff7
Update flows_planktonscope.json 2019-12-14 20:37:53 -08:00
tpollina 0879e4a2dc
Update flows_planktonscope.json 2019-12-14 17:05:05 -08:00
tpollina fbfd094e25
Update flows_planktonscope.json 2019-12-14 15:48:37 -08:00
tpollina 44dc6cbf0d
Update flows_planktonscope.json 2019-12-14 01:41:26 -08:00
tpollina 19a10a56c3
Update flows_planktonscope.json 2019-12-14 01:33:43 -08:00
tpollina 2dadb01634
Add files via upload 2019-12-14 01:33:17 -08:00
tpollina e9a05ee21d
Update flows_planktonscope.json 2019-12-13 22:11:09 -08:00
tpollina d950c8536f
Create flows_planktonscope.json 2019-12-13 22:09:26 -08:00
tpollina 3f584454c2
Add files via upload 2019-12-13 22:02:00 -08:00
tpollina 9a9ff63fd9
Update README.md 2019-12-13 15:09:07 -08:00
tpollina 1a9eb04de1
Create fan.py 2019-12-13 15:00:20 -08:00
tpollina aa23d66bd2
Add files via upload 2019-12-13 14:51:50 -08:00
tpollina db23d48f8d
Update focus.py 2019-12-13 14:40:35 -08:00
tpollina 3f77fcc267
Update pump.py 2019-12-13 14:40:20 -08:00
tpollina 2f9d748576
Update README.md 2019-12-13 14:20:48 -08:00
tpollina bb893b19fe
Update kill_image.sh 2019-12-13 14:20:31 -08:00
tpollina 47f66dd1c8
Update killer.sh 2019-12-13 14:20:03 -08:00
tpollina e03eaa9d08
Update light.py 2019-12-13 14:13:23 -08:00
tpollina 37fb6bffd8
Update README.md 2019-12-13 14:12:56 -08:00
tpollina c9fc2cb07c
Update pump.py 2019-12-13 14:11:55 -08:00
tpollina 0652cb95ca
Create README.md 2019-12-13 13:34:45 -08:00
tpollina 1d189ed52a
Update killer.sh 2019-12-13 13:03:07 -08:00
tpollina 5e148cbd60
Create kill_image.sh 2019-12-13 13:01:38 -08:00
tpollina 6c7e68bcb5
Update image.py 2019-12-13 13:01:34 -08:00
tpollina 99f1d7bb9f
Create recover.py 2019-12-13 12:39:16 -08:00
tpollina 760bb101f9
Update image.py 2019-12-13 12:34:09 -08:00
tpollina c7cb995ac7
Update focus.py 2019-12-13 12:30:57 -08:00
tpollina 52467bb9fa
Update pump.py 2019-12-13 12:30:03 -08:00
tpollina 9b9443558e
Update light.py 2019-12-13 12:28:39 -08:00
tpollina 502fe343f1
Create killer.sh 2019-12-13 12:26:35 -08:00
tpollina 050f50a3c1
Update image.py 2019-12-13 12:15:20 -08:00
tpollina 8af111e528
Create image.py 2019-12-13 11:59:53 -08:00
tpollina a099f11031
Update light.py 2019-12-13 10:53:52 -08:00
tpollina 7141c117e7
Create light.py 2019-12-13 10:49:19 -08:00
tpollina 61ec2fd6b7
Create pump.py 2019-12-13 10:39:50 -08:00
tpollina 1d68a1aac2
Update and rename main.py to focus.py 2019-12-13 10:38:55 -08:00
tpollina 92bcc52225
Create main.py 2019-12-13 10:36:27 -08:00