-
Notifications
You must be signed in to change notification settings - Fork 58
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Adding 2020 examples as CSVs #25
base: main
Are you sure you want to change the base?
Conversation
So, I'm not the author of any of these, but looking at some key animations like fire and 3dfire I'm almost certain that you forgot to rearrange the color "sub-pixels" so to speak. Fire typically is red, both fire animations are (a) pretty dim (but that could have been intentional) and (b) more green than red. The RPi uses the color-coding GRB, so you have to interpret them accordingly. |
I didn't make "lightning" |
@Diggsey Thank you! I am now attributing 'lightning' to the correct author upon inspecting commit histories. |
Thanks, @d-albrecht! Nice catch, green fire felt fine to me for some reason. Will be fixing.
|
Hey thanks for running my script and crediting me! I'm not going to bother verifying the output since it's so long and I plan on doing something different this year, but I hope it runs! It should be fine since the one thing I forgot last year was to tell the lights to turn on... |
Alternatively write a small script that swaps the colors around. That might be easier than integrating this into your replay analysis. You know, single responsibility principle! And as long as your rust code invokes this script automatically, no-one has to know that your replay analysis gets the colors wrong. ;) |
I need to check how it looks with the pre-rendered method 😀 I was unable to test my code on the real hardware before submitting it and it ended to be pretty slow (there are probably way of optimising it like not using Python XD ) but an actual 3D frame buffer and finding matching LEDs and doing average for each pixel is not a simple light task. And thanks for the porting effort 😀 Edit: for 3D plasma, I originally dimmed the light quite a lot because Matt said his power supply was weak and as most LED are on with that effect, I wanted to stay safe. Something is off with the fire, need to check what is happening, but it could be due the simulator I was using and you rendering with a different GIFT file. (though I fear my effect may render weird on a real tree with how matt fixed the lights in the wrong position) |
About rgb-spheres, it is supposed to repeat after 4800 frames, but because of a rounding error and the initial random starting radius not being based on a whole frame number, this is not the case with the file present in the 2020 repository. I fixed those bugs now, to make a repeating animation for this format. Here is a loopable csv file: https://www.dropbox.com/s/rzmb6xkn42rfzjd/rgb-spheres.csv?dl=0 And for reference the fixed code. Changed lines are 108 and 126. def xmaslight():
# This is the code from my
#NOTE THE LEDS ARE GRB COLOUR (NOT RGB)
# Here are the libraries I am currently using:
import time
#from sim import board
#from sim import neopixel
import board
import neopixel
import re
import math
import random
# You are welcome to add any of these:
# import numpy
# import scipy
# import sys
# If you want to have user changable values, they need to be entered from the command line
# so import sys sys and use sys.argv[0] etc
# some_value = int(sys.argv[0])
# IMPORT THE COORDINATES (please don't break this bit)
#coordfilename = "./coords.txt"
coordfilename = "Python/coords.txt"
fin = open(coordfilename,'r')
coords_raw = fin.readlines()
coords_bits = [i.split(",") for i in coords_raw]
coords = []
for slab in coords_bits:
new_coord = []
for i in slab:
new_coord.append(int(re.sub(r'[^-\d]','', i)))
coords.append(new_coord)
#set up the pixels (AKA 'LEDs')
PIXEL_COUNT = len(coords) # this should be 500
pixels = neopixel.NeoPixel(board.D18, PIXEL_COUNT, auto_write=False)
# YOU CAN EDIT FROM HERE DOWN
# Calculates the distance of 2 vectors
def vdist(v1: list, v2: list):
if len(v1) != len(v2):
return -1
result = 0
for i in range(len(v1)):
result += (v1[i] - v2[i]) ** 2
return math.sqrt(result)
# Find coordinate that maximizes the distance for a given set of other coords
def find_furthest(points: list):
max_dist = 0
cur_pnt = points[0]
for coord in coords:
dist = math.inf
for p in points:
p_dist = vdist(p, coord)
if p_dist < dist:
dist = p_dist
if (dist > max_dist):
max_dist = dist
cur_pnt = coord
return cur_pnt
# init sphere origins.
# First sphere's origin is furthest from the coordinate system's origin
# Second sphere's origin is the LED with the greatest distance from the first sphere's origin
# Third sphere's origin is the LED where the distance for both other spheres is maximized.
sphere_origins = []
sphere_origins.append(find_furthest([[0, 0, 0]]))
sphere_origins.append(find_furthest(sphere_origins))
sphere_origins.append(find_furthest(sphere_origins))
# calculate maximum distance of any LED for each sphere's origin.
# Used to determine the max radius each sphere will ever receive
max_dists = [0, 0, 0]
for coord in coords:
for i in range(3):
dist = vdist(coord, sphere_origins[i])
if max_dists[i] < dist:
max_dists[i] = dist
# The rate in which each sphere enlargens. When negative, the sphere is currently shrinking.
increment_rates = [0, 0, 0]
# The radius of each sphere. Initial value is randomized
radii = [0, 0, 0]
# set initial increment rates and radii
for i in range(3):
# Frames per cycle for current sphere
frames = i * 40 + 120
increment_rates[i] = max_dists[i] / frames
# Random start radius
radii[i] = int(random.random() * frames) * increment_rates[i]
# infinitly many frames. Wohoo.
while True:
for i in range(PIXEL_COUNT):
# calculate color for current pixel. Each rgb (grb) color value is 255 * dist / max_dist
color = [0, 0, 0]
for s in range(3):
dist = abs(vdist(sphere_origins[s], coords[i]) - radii[s])
color[s] = int(255 * (1 - dist / max_dists[s]) ** 3)
pixels[i] = color
pixels.show()
# calculate radii for next iteration.
for s in range(3):
# Switch from enlarging to shrinking and vice versa, as needed
new_radius = radii[s] + increment_rates[s]
if new_radius > max_dists[s] + 1e-5 or new_radius < -1e-5:
increment_rates[s] = -increment_rates[s]
radii[s] += increment_rates[s]
return 'DONE'
# yes, I just put this at the bottom so it auto runs
xmaslight() |
Hello, thanks for taking the time to do this! At a glance I would say salesman.py was converted correctly, there are 502 lines and they seem to gradually light more LEDs, so it certainly passes the basic sanity check. But... Has the exact same tree been recreated? I don't have any context as to what is going on with the tree but it is only going to work if it is the exact same tree with the exact same bulb configuration. If the bulbs are in different locations then obviously the traveling salesman solution will not work anymore. The solution was precomputed and hardcoded because computing it took hours. 😄 Just NP problems... |
@SimonRovder Hi! Thank you for making the animation in the first place, it's a great addition and I really liked it!
Yes, I took your exact same submitted code from last year and made the new CSV with it. The produced animation does not perfectly match 2021's coordinates.
If you would like to update the salesman solution, that would be great! I would be glad to generate the CSV again, it would be no problem and better to have the animation be correct. For the most part, I think the current animation looks good and gets the effect across, though you sometimes do notice the traversal jumping incorrectly. You can review your animation using a simulator such as MPTree (mine) or other ones found linked in this repo or PRs. |
@Godzil I re-rendered the 3dplasma animation and changed dimLight to 0.5 as suggested. Looks good, thank you! The 3dfire animation was also updated during the fix of RGB instead of GRB issue. Hopefully it looks better for everyone now. :) |
@NeunEinser Hi, I updated the file to be the one you shared for looping rgb-spheres. Thanks! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The salesman.csv example needs to be removed, it will not work for the new tree configuration and just look all wrong. Since we're dealing with an NP problem, the solution was hardcoded for last year's tree (it took hours to compute).
I definitely don't have the time to get a new solution up right now, sorry guys. 😢 Can it be removed?
@SimonRovder salesman.csv is now removed. Thank you for being attentive to this PR anyway! |
2020 Examples
These examples were taken from the standupmaths/xmastree2020 repository.
The python scripts from 2020 were processed using santiagodg/xmastree-2020py-to-2021csv to generate 2021's animation CSV files and sometimes manually modifying them to make them work.
These CSVs have not been verified by the original animators.
Credits
Animation: Original Author