Skip to content

Commit

Permalink
Tidied up readme
Browse files Browse the repository at this point in the history
replaced some prints with logging
fixed camera checker scripts
  • Loading branch information
TheMariday committed Jul 15, 2024
1 parent 052cda9 commit 777f7b3
Show file tree
Hide file tree
Showing 7 changed files with 99 additions and 64 deletions.
92 changes: 55 additions & 37 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,35 +19,11 @@ The basic algorithms behind this is what I used to map [Highbeam](https://www.yo

## Step 0: Install

You can install Marimapper with just Python and Pip! No clone required!

For the Marimapper to communicate with your leds, it requires a backend.

Luckily, the following backends are pre-built:

- `fadecandy`
- [`wled`](https://kno.wled.ge/)
- [`fcmega`](https://github.com/TheMariday/FC-Mega)
- [`pixelblaze`](https://electromage.com/docs)

To install Marimapper with a
`pixelblaze`
backend, run the following command:

`pip install "marimapper[pixelblaze] @ git+http://github.com/themariday/marimapper"`

<details>
<summary>Using pixelblaze?</summary>
Using Pixelblaze as a backend requires you to upload the [`marimapper.epe`](marimapper/backends/pixelblaze/marimapper.epe) pattern to your pixelblaze before running Marimapper.
</details>

If you would like to write your own LED backend, run the following command:
Install MariMapper with:

`pip install "marimapper @ git+http://github.com/themariday/marimapper"`


## Step 1: Run the camera checker (recommended)

## Step 1: Test your camera

Run `marimapper_check_camera` to ensure your camera is compatible with MariMapper, or check the list below:

Expand Down Expand Up @@ -82,15 +58,49 @@ As long as your webcam has exposure control, this should even work in a relative
> [!TIP]
> If your camera doesn't support exposure adjustment, or the image is still too bright, try dimming the lights and playing around with the --exposure and --threshold arguments
## Step 2: Choose your backend

## Step 2: Write your LED backend if needed
For the Marimapper to communicate with your leds, it requires a backend.

If your LED backend isn't supported, you need to write your own!
This is luckily very simple!
The following backends are built-in:

Open a new python file called `my_backend.py` and copy the below stub into it.
<details>
<summary>Fadecandy</summary>

Fill out the blanks and check it by running `marimapper_check_backend --backend my_backend.py`
To use the fadecandy backend, please ensure that you are running the fadecandy server
A fork of the fadecandy repo can be found [here](https://github.com/TheMariday/fadecandy)

</details>

<details>
<summary>WLED</summary>

More info can be found [here](https://kno.wled.ge/)

</details>

<details>
<summary>FCMega</summary>

This is a custom driver I've written for the Teensy 4.1 to drive up to 9600 leds.
Source code can be found [here](https://github.com/TheMariday/fcmega)

</details>

<details>
<summary>PixelBlaze</summary>

Using Pixelblaze as a backend requires you to upload the
[marimapper.epe](https://github.com/TheMariday/marimapper/backends/pixelblaze/marimapper.epe) pattern to your pixelblaze before running Marimapper.

</details>

To install any of the above backends, run:

`pip install "marimapper[backend_name] @ git+http://github.com/themariday/marimapper"`

If your LED backend isn't supported, you need to write your own.
Open a new python file called `my_backend.py` and copy the below stub into it.

```python
class Backend:
Expand All @@ -111,22 +121,30 @@ class Backend:
# some_led_library.set_led(led_index, (0, 0, 0))
```

Fill out the blanks and check it by running `marimapper_check_backend --backend my_backend.py`


## Step 3: [It's time to thunderize!](https://youtu.be/-5KJiHc3Nuc?t=121)

Run `marimapper my_scan --backend fadecandy`
Run `marimapper my_scan --backend fadecandy`

Change `fadecandy` to whatever backend you're using
and `my_scan` to the directory you want to save your scan
Change `my_scan` to the directory you want to save your scan
and `fadecandy` to whatever backend you're using

Set up your LEDs so most of them are in view and when you're ready, type `y` when prompted with `Start scan? [y/n]`

This will turn each LED on and off in turn, do not move the camera or leds during capture!

If you just want a 2D map, this is where you can stop!
<details>
<summary>Just want a 2D map?</summary>

If you just want a 2D map, this is where you can stop!

Run `python scripts/view_2d_map.py my_scan/...` to visualise your map replacing `...` with the map name.
Run `marimapper_view_2d_scan led_map_2d_0.csv` to visualise your map replacing `led_map_2d_0.csv` with the map name.

</details>

To capture a 3D map, rotate your leds or move your webcam to a new position
Rotate your leds or move your webcam to a new position

> [!TIP]
> As long as some of your leds are mostly in view, you can move your webcam to wherever you like!
Expand Down
7 changes: 4 additions & 3 deletions marimapper/backends/fcmega/fcmega.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import serial
import struct
import serial.tools.list_ports
from marimapper import logging


class FCMega:
Expand All @@ -12,13 +13,13 @@ def __init__(self, port=None):
if port is None:
port = self._get_port()
if port is None:
print("Cannot find port")
logging.error("Cannot find port")
return

self.serial = serial.Serial(port)

if not self.update():
print("failed to communicate with FC MEga")
logging.error("failed to communicate with FC MEga")
return

def __del__(self):
Expand All @@ -27,7 +28,7 @@ def __del__(self):
def _get_port(self):
for device in serial.tools.list_ports.comports():
if device.serial_number.startswith("FCM"):
print(f"found port {device.name}")
logging.info(f"found port {device.name}")
return device.name

return None
Expand Down
3 changes: 2 additions & 1 deletion marimapper/backends/pixelblaze/pixelblaze_backend.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from marimapper import logging
import pixelblaze


Expand All @@ -11,7 +12,7 @@ def __init__(self, pixelblaze_ip="4.3.2.1"):

def get_led_count(self):
pixel_count = self.pb.getPixelCount()
print(f"Pixelblaze reports {pixel_count} pixels")
logging.info(f"Pixelblaze reports {pixel_count} pixels")
return pixel_count

def set_led(self, led_index: int, on: bool):
Expand Down
28 changes: 8 additions & 20 deletions marimapper/backends/pixelblaze/upload_map_to_pixelblaze.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import argparse
import csv

from marimapper import utils
from marimapper import logging


def read_coordinates_from_csv(csv_file_name):
print(f"Loading coordinates from {csv_file_name}")
logging.info(f"Loading coordinates from {csv_file_name}")
with open(csv_file_name, newline="") as csvfile:
csv_reader = csv.DictReader(csvfile)
list_of_leds = []
Expand All @@ -31,31 +31,19 @@ def read_coordinates_from_csv(csv_file_name):
return final_coordinate_list


def main_function(cli_args):
def upload_map_to_pixelblaze(cli_args):
final_coordinate_list = read_coordinates_from_csv(cli_args.csv_file)
print(final_coordinate_list)
logging.info(final_coordinate_list)

upload_coordinates = utils.get_user_confirmation(
"Upload coordinates to Pixelblaze? [y/n]: "
)
if not upload_coordinates:
return

print(f"Uploading coordinates to pixelblaze {cli_args.server}")
logging.info(
f"Uploading coordinates to pixelblaze {cli_args.server if cli_args.server is not None else ''}"
)
led_backend = utils.get_backend("pixelblaze", cli_args.server)
led_backend.set_map_coordinates(final_coordinate_list)
print("Finished")


if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Upload led_map_3d.csv to pixelblaze")
parser.add_argument("--server", type=str, help="pixelblaze server ip")
parser.add_argument(
"--csv_file",
type=str,
help="The csv file to convert",
default="my_scan/led_map_3d.csv",
)
args = parser.parse_args()

main_function(args)
logging.info("Finished")
19 changes: 19 additions & 0 deletions marimapper/scripts/upload_map_to_pixelblaze_cli.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import argparse
from marimapper.backends.pixelblaze.upload_map_to_pixelblaze import (
upload_map_to_pixelblaze,
)


def main():
parser = argparse.ArgumentParser(description="Upload led_map_3d.csv to pixelblaze")
parser.add_argument("--server", type=str, help="pixelblaze server ip")
parser.add_argument(
"--csv_file", type=str, help="The csv file to convert", required=True
)
args = parser.parse_args()

upload_map_to_pixelblaze(args)


if __name__ == "__main__":
main()
7 changes: 4 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ Repository = "https://github.com/themariday/marimapper.git"

[project.scripts]
marimapper = "marimapper.scripts.scanner_cli:main"
marimapper_check_camera = "marimapper.scripts.check_camera:main"
marimapper_check_backend ="marimapper.scripts.check_backend:main"

marimapper_check_camera = "marimapper.scripts.check_camera_cli:main"
marimapper_check_backend ="marimapper.scripts.check_backend_cli:main"
marimapper_upload_to_pixelblaze = "marimapper.scripts.upload_map_to_pixelblaze_cli:main"
marimapper_view_2d_map = "marimapper.scripts.view_2d_map_cli:main"
7 changes: 7 additions & 0 deletions test/test_script_import.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,11 @@ def test_view_2d_map_cli():
main() # This should fail gracefully without any arguments


def test_upload_to_pixelblaze_cli():
from marimapper.scripts.upload_map_to_pixelblaze_cli import main

with pytest.raises(SystemExit):
main() # This should fail gracefully without any arguments


# Do not test scanner_cli due to it calling system level sig-kill commands!

0 comments on commit 777f7b3

Please sign in to comment.