Skip to content

Instantly share code, notes, and snippets.

@kokimame
Created July 23, 2017 13:44
Show Gist options
  • Select an option

  • Save kokimame/3ff6b6e2301349d4d714dcb652b7bead to your computer and use it in GitHub Desktop.

Select an option

Save kokimame/3ff6b6e2301349d4d714dcb652b7bead to your computer and use it in GitHub Desktop.
mini project to submit as HW

Smart Lighting Simulation

This simulation's goal is to make lighting provide a desirable light to each user.

Currently the optimization only uses a simple heuristic because it seems hard to apply other smart algorithms to this system.

Demo

In the demo below, the users at the desks (shown in purple rectangles) have their own request for the amount of light (illuminance; lx) on their desks, and then they all set it to 500 lx at the halfway along the demo. As the users chenge their request, 12 light sources (show in dark and bright yellow circles) adjust its luminous intensity (candela: cd) to meet the users' demand.

You see the color of the circle on each desk, which represents the actual lx on the desk, converges to the color of the desk, which represents the demanding lx of the user. Thus the optimization has been successfully completed.

import rendering
ROOMW, ROOMH = 600, 400
SCALE = ROOMW / 5400
OFFX, OFFY = 100, 50
viewer = rendering.Viewer(ROOMW + 2 * OFFX, ROOMH + 2 * OFFY)
lights_p = [(0, 0, 0), (1800, 0, 1), (3600, 0, 2), (5400, 0, 3),
(0, 1800, 4), (1800, 1800, 5), (3600, 1800, 6), (5400, 1800, 7),
(0, 3600, 8), (1800, 3600, 9), (3600, 3600, 10), (5400, 3600, 11)]
init_cd = 0
desks_p = [
(1000, 2150, 900, 0, (5,4,9,8,1,0)), (2200, 2150, 700, 1, (5,6,9,10,1,2)),
(3400, 2150, 500, 2, (6,5,10,9,2,1)),(1000, 2850, 700, 3, (9,8,5,4)),
(2200, 2850, 500, 4, (9,5,10,6)), (3400, 2850, 300, 5,(10,6,9,5,7,11))]
def cd2lx3d(v1, v2, cd, h=2000):
dst = ((v1[0] - v2[0])**2 + (v1[1] - v2[1])**2 + h**2)**0.5
cos = h / dst
return cos * cd / dst ** 2 * 1000**2
class Light:
MAXCD = 2500 # Maximum value of candela
def __init__(self, pos, cd, _id):
self.cd = cd
self.pos = pos
self._id = _id
x, y = pos
x, y = x * SCALE, y * SCALE
self.shape = rendering.make_circle(x + OFFX, y + OFFY)
self.set_color()
viewer.add_geom(self.shape)
def update_cd(self, dcd):
self.cd += dcd
self.cd = 0 if self.cd < 0 else self.cd
self.cd = Light.MAXCD if self.cd > Light.MAXCD else self.cd
self.set_color()
def set_color(self):
color_scale = self.cd / Light.MAXCD
rgb = (color_scale, color_scale, 0)
self.shape.set_color(*rgb)
class Desk:
W, H = 1200, 700
Ws, Hs = 1200 * SCALE, 700 * SCALE
def __init__(self, pos, tlx, _id, nears):
self.tlx = tlx # Target lx of the desk
self.pos = pos
self._id = _id
self.nears = nears
self.err = 0
x, y = pos
x, y = x * SCALE, y * SCALE
lx, rx = x - Desk.Ws/2 + OFFX, x + Desk.Ws/2 + OFFX
by, ty = y - Desk.Hs/2 + OFFY, y + Desk.Hs/2 + OFFY
self.shape = rendering.FilledPolygon([(lx,by),(lx,ty),(rx,ty),(rx,by)])
self.center = rendering.make_circle(x + OFFX, y + OFFY, radius=Desk.Hs/4)
self.set_shape_color()
self.set_center_color(self.tlx)
viewer.add_geom(self.shape)
viewer.add_geom(self.center)
viewer.draw_polyline([(lx,by),(lx,ty),(rx,ty),(rx,by)])
# Updating method for cd of nearby lights
def adjust_n_lights(self, lights):
n_light = [light for light in lights if light._id in self.nears]
for i, light in enumerate(n_light):
dcd = -self.err/ 10 * (len(n_light) - i)
light.update_cd(dcd)
def adjust_lights(self, lights):
for light in lights:
dcd = -self.err/100 * self.distance_to(light)
light.update_cd(dcd)
def distance_to(self, light):
x1, y1 = self.pos
x2, y2 = light.pos
return ((x1-x2)**2 + (y1-y2)**2)**0.5
def set_tlx(self, new_tlx):
self.tlx = new_tlx
self.set_shape_color()
def set_shape_color(self):
color_scale = self.tlx / 1000
r, g, b = 0.8 * color_scale, 0.1 * color_scale, 0.7 * color_scale
self.shape.set_color(r, g, b)
def set_center_color(self, lx):
color_scale = lx / 1000
r, g, b = 0.8 * color_scale, 0.1 * color_scale, 0.7 * color_scale
self.center.set_color(r, g, b)
# Initialize lights and desks
desks = [ Desk((desk_p[0], desk_p[1]), desk_p[2], desk_p[3], desk_p[4]) for desk_p in desks_p]
lights = [ Light((light_p[0],light_p[1]), init_cd, light_p[2]) for light_p in lights_p ]
def episode(N):
for _ in range(N):
sterr = 0
for desk in desks:
dlight = 0
for light in lights:
dlight += cd2lx3d(desk.pos, light.pos, light.cd)
desk.err = dlight - desk.tlx
# Adjust cd of light heuristically based on error at a desk
desk.adjust_n_lights(lights)
desk.set_center_color(dlight)
viewer.render()
episode(50)
[desk.set_tlx(500) for desk in desks]
episode(100)
[ print("Light ID", light._id, ":", light.cd) for light in lights ]
print([desk.err for desk in desks])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment