Project Duna

Latest raw images from Mars on your wall

I made this project a while back, after Perseverance landed on Mars. I had an old LCD screen and an unused Raspberry Pi, and I thought it would be neat to have a slideshow of images from Mars on my wall. I found that NASA provides a simple REST API for querying the list of available raw images. The API requires registration, but it’s completely free. The main difficulty was figuring out which images to display. Both rovers have multiple cameras and produce lots of data. They’re all interesting in their own way, but many of them aren’t perfectly suitable for the slideshow. There are test or calibration images, tiny low-res images, etc. The file names seem to encode more information about each image, but I couldn’t find the exact meaning of each component.

# Example file name of Curiosity Mastcam image:
0606MR0025610090400978E01_DXXX.jpg

# Example file name of Perseverance Mastcam image:
ZL0_0698_0728909553_054EBY_N0330000ZCAM08697_1100LMJ01_1200.jpg

To be clear, these are raw images, so there will always be plenty of similar-looking pictures of the ground, sky, instruments, individual parts of panoramic mosaics, etc.

In the end, I downloaded a batch of pictures from different cameras and tried to make educated guesses about which files to select for the slideshow. I ended up with the following filters.

class CuriosityApi(RoverApi):
    def wantImage(self, img):
        name = getFileName(img[0])
        cat = name[22:25]
        # Cxx and Exx images from mastcam seem to be the most interesting
        return (cat[0] == "C" or cat[0] == "E") or 'NCAM' in name

class PerseveranceApi(RoverApi):
    def wantImage(self, img):
        name = getFileName(img[0])
        # "EBY" seem to be the most interesting
        # 3rd char is the filter. 0 and 7 is no filter.
        return ('EBY' in name) \
            and (name[2] == '0' or name[2] == '7') \
            and ('CAM01000' not in name)

The code regularly checks for new data that match the above criteria and downloads the new images. The latest set is then used to make the slideshow for that particular rover.

Later, I also added a composite image of four hazard avoidance cameras from Perseverance. If all four pictures are available on that sol, it creates a nice 4-way view like this:

Finally, I added the latest Astronomy Picture Of the Day (APOD) and the ability to show web pages as part of the slide show. I use it to show upcoming rocket launches, Clear Sky charts in my area, and a few others.

After test running the program for a few days, I noticed that sometimes, pictures from one rover overwhelm the slideshow. This is natural because, on some sols, one rover will produce lots of data, while the other might only send a few. To balance the slideshow, I split the images into three “channels”. One for each rover, and a 3rd channel for the static pages. The slideshow then interleaves batches of pictures from each channel. So a typical sequence might look like this:

Curiosity picture 1
Curiosity picture 2
Curiosity picture 3
Perseverance picture 1
Perseverance picture 2
Perseverance picture 3
APOD
Static page 1
Static page 2
Curiosity picture 4
…

Everything is configured via a JSON file in the home directory. The configuration includes the API key and the list of static images and web pages.

Over time, the downloaded images started to use up quite a lot of disk space, so I added a shell script scheduled as a cron job to clean up the oldest files. Finally, I added a pair of cron jobs to turn the screen off for the night.

# m h  dom mon dow   command
5 0 * * * /opt/duna/bin/limit_disk_usage.sh /var/lib/duna/rovers
# turn off at midnight
0 0 * * * DISPLAY=:0 xrandr --output HDMI-1 --off
# turn on at 7am
0 7 * * * DISPLAY=:0 xrandr --output HDMI-1 --auto

The project can be found on GitHub:
https://github.com/marcinb64/duna

Leave a Reply

Your email address will not be published. Required fields are marked *