forecast trajectories don't transition, but remain and fade out
This commit is contained in:
parent
e837617e39
commit
9871848407
2 changed files with 65 additions and 45 deletions
|
@ -95,9 +95,7 @@ class Track:
|
||||||
coords = self.get_projected_history(H)
|
coords = self.get_projected_history(H)
|
||||||
return [{"x":c[0], "y":c[1]} for c in coords]
|
return [{"x":c[0], "y":c[1]} for c in coords]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class Frame:
|
class Frame:
|
||||||
|
|
108
trap/renderer.py
108
trap/renderer.py
|
@ -24,11 +24,25 @@ from pyglet import shapes
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
|
|
||||||
from trap.frame_emitter import DetectionState, Frame, Track
|
from trap.frame_emitter import DetectionState, Frame, Track
|
||||||
|
from dataclasses import dataclass
|
||||||
|
|
||||||
|
|
||||||
logger = logging.getLogger("trap.renderer")
|
logger = logging.getLogger("trap.renderer")
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class LineAnimConfig:
|
||||||
|
start_opacity: float
|
||||||
|
target_opacity: float
|
||||||
|
decay: float
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class AnimConfig:
|
||||||
|
clear_color = (0,0,0,0)
|
||||||
|
video_opacity = 100 # on 255 scale
|
||||||
|
tracks: LineAnimConfig = LineAnimConfig(80, 180, 60)
|
||||||
|
predictions: LineAnimConfig = LineAnimConfig(20, 50, 10)
|
||||||
|
|
||||||
|
|
||||||
class FrameAnimation:
|
class FrameAnimation:
|
||||||
def __init__(self, frame: Frame):
|
def __init__(self, frame: Frame):
|
||||||
self.start_time = time.time()
|
self.start_time = time.time()
|
||||||
|
@ -101,8 +115,8 @@ class DrawnTrack:
|
||||||
'''
|
'''
|
||||||
# TODO: make lerp, currently quick way to get results
|
# TODO: make lerp, currently quick way to get results
|
||||||
for i, pos in enumerate(self.drawn_positions):
|
for i, pos in enumerate(self.drawn_positions):
|
||||||
self.drawn_positions[i][0] = int(exponentialDecay(self.drawn_positions[i][0], self.coords[i][0], 16, dt))
|
self.drawn_positions[i][0] = int(exponentialDecay(self.drawn_positions[i][0], self.coords[i][0], AnimConfig.tracks.decay, dt))
|
||||||
self.drawn_positions[i][1] = int(exponentialDecay(self.drawn_positions[i][1], self.coords[i][1], 16, dt))
|
self.drawn_positions[i][1] = int(exponentialDecay(self.drawn_positions[i][1], self.coords[i][1], AnimConfig.tracks.decay, dt))
|
||||||
|
|
||||||
if len(self.coords) > len(self.drawn_positions):
|
if len(self.coords) > len(self.drawn_positions):
|
||||||
self.drawn_positions.extend(self.coords[len(self.drawn_positions):])
|
self.drawn_positions.extend(self.coords[len(self.drawn_positions):])
|
||||||
|
@ -151,7 +165,7 @@ class DrawnTrack:
|
||||||
if ci >= len(self.shapes):
|
if ci >= len(self.shapes):
|
||||||
# TODO: add color2
|
# TODO: add color2
|
||||||
line = self.renderer.gradientLine(x, y, x2, y2, 3, color, color, batch=self.renderer.batch_anim)
|
line = self.renderer.gradientLine(x, y, x2, y2, 3, color, color, batch=self.renderer.batch_anim)
|
||||||
line.opacity = 5
|
line.opacity = AnimConfig.tracks.start_opacity
|
||||||
self.shapes.append(line)
|
self.shapes.append(line)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
@ -159,50 +173,53 @@ class DrawnTrack:
|
||||||
line.x, line.y = x, y
|
line.x, line.y = x, y
|
||||||
line.x2, line.y2 = x2, y2
|
line.x2, line.y2 = x2, y2
|
||||||
line.color = color
|
line.color = color
|
||||||
line.opacity = int(exponentialDecay(line.opacity, 180, 3, dt))
|
line.opacity = int(exponentialDecay(line.opacity, AnimConfig.tracks.target_opacity, AnimConfig.tracks.start_opacity, dt))
|
||||||
|
|
||||||
# TODO: basically a duplication of the above, do this smarter?
|
# TODO: basically a duplication of the above, do this smarter?
|
||||||
# TODO: add intermediate segment
|
# TODO: add intermediate segment
|
||||||
color = colorset[self.track_id % len(colorset)]
|
#color = colorset[self.track_id % len(colorset)]
|
||||||
|
|
||||||
for a, drawn_predictions in enumerate(self.drawn_predictions):
|
for drawn_prediction in self.predictions:
|
||||||
if len(self.pred_shapes) <= a:
|
drawn_prediction.update_opacities(dt)
|
||||||
self.pred_shapes.append([])
|
|
||||||
|
# for a, drawn_predictions in enumerate(self.drawn_predictions):
|
||||||
|
# if len(self.pred_shapes) <= a:
|
||||||
|
# self.pred_shapes.append([])
|
||||||
|
|
||||||
if len(self.pred_shapes[a]) > (len(drawn_predictions) +1):
|
# if len(self.pred_shapes[a]) > (len(drawn_predictions) +1):
|
||||||
self.pred_shapes[a] = self.pred_shapes[a][:len(drawn_predictions)]
|
# self.pred_shapes[a] = self.pred_shapes[a][:len(drawn_predictions)]
|
||||||
|
|
||||||
# for i, pos in drawn_predictions.enumerate():
|
# # for i, pos in drawn_predictions.enumerate():
|
||||||
for ci in range(0, len(drawn_predictions)):
|
# for ci in range(0, len(drawn_predictions)):
|
||||||
if ci == 0:
|
# if ci == 0:
|
||||||
x, y = [int(p) for p in self.drawn_positions[-1]]
|
# x, y = [int(p) for p in self.drawn_positions[-1]]
|
||||||
else:
|
# else:
|
||||||
x, y = [int(p) for p in drawn_predictions[ci-1]]
|
# x, y = [int(p) for p in drawn_predictions[ci-1]]
|
||||||
|
|
||||||
x2, y2 = [int(p) for p in drawn_predictions[ci]]
|
# x2, y2 = [int(p) for p in drawn_predictions[ci]]
|
||||||
|
|
||||||
y, y2 = self.renderer.window.height - y, self.renderer.window.height - y2
|
# y, y2 = self.renderer.window.height - y, self.renderer.window.height - y2
|
||||||
# color = [255,0,0]
|
# # color = [255,0,0]
|
||||||
# print(x,y,x2,y2,color)
|
# # print(x,y,x2,y2,color)
|
||||||
|
|
||||||
if ci >= len(self.pred_shapes[a]):
|
# if ci >= len(self.pred_shapes[a]):
|
||||||
# TODO: add color2
|
# # TODO: add color2
|
||||||
line = self.renderer.gradientLine(x, y, x2, y2, 3, color, color, batch=self.renderer.batch_anim)
|
# line = self.renderer.gradientLine(x, y, x2, y2, 3, color, color, batch=self.renderer.batch_anim)
|
||||||
line.opacity = 5
|
# line.opacity = 5
|
||||||
self.pred_shapes[a].append(line)
|
# self.pred_shapes[a].append(line)
|
||||||
|
|
||||||
else:
|
# else:
|
||||||
line = self.pred_shapes[a][ci-1]
|
# line = self.pred_shapes[a][ci-1]
|
||||||
line.x, line.y = x, y
|
# line.x, line.y = x, y
|
||||||
line.x2, line.y2 = x2, y2
|
# line.x2, line.y2 = x2, y2
|
||||||
line.color = color
|
# line.color = color
|
||||||
decay = (16/ci) if ci else 16
|
# decay = (16/ci) if ci else 16
|
||||||
half = len(drawn_predictions) / 2
|
# half = len(drawn_predictions) / 2
|
||||||
if ci < half:
|
# if ci < half:
|
||||||
target_opacity = 180
|
# target_opacity = 180
|
||||||
else:
|
# else:
|
||||||
target_opacity = (1 - ((ci - half) / half)) * 180
|
# target_opacity = (1 - ((ci - half) / half)) * 180
|
||||||
line.opacity = int(exponentialDecay(line.opacity, target_opacity, decay, dt))
|
# line.opacity = int(exponentialDecay(line.opacity, target_opacity, decay, dt))
|
||||||
|
|
||||||
class DrawnPrediction:
|
class DrawnPrediction:
|
||||||
def __init__(self, drawn_track: DrawnTrack, coords: list[list] = []):
|
def __init__(self, drawn_track: DrawnTrack, coords: list[list] = []):
|
||||||
|
@ -245,13 +262,17 @@ class DrawnPrediction:
|
||||||
# line.x, line.y = x, y
|
# line.x, line.y = x, y
|
||||||
# line.x2, line.y2 = x2, y2
|
# line.x2, line.y2 = x2, y2
|
||||||
# line.color = color
|
# line.color = color
|
||||||
decay = (16/ci) if ci else 16
|
|
||||||
|
# lower decay for further points slows down fade in
|
||||||
|
decay = (AnimConfig.predictions.decay/(3*ci)) if ci else AnimConfig.predictions.decay
|
||||||
half = len(coords) / 2
|
half = len(coords) / 2
|
||||||
|
|
||||||
if ci < half:
|
if ci < half:
|
||||||
target_opacity = 180
|
target_opacity = AnimConfig.predictions.target_opacity
|
||||||
else:
|
else:
|
||||||
target_opacity = (1 - ((ci - half) / half)) * 180
|
target_opacity = (1 - ((ci - half) / half)) * AnimConfig.predictions.target_opacity
|
||||||
line.opacity = int(exponentialDecay(line.opacity, target_opacity, decay, dt))
|
line.opacity = int(exponentialDecay(line.opacity, target_opacity, decay, dt))
|
||||||
|
# logger.info(f"{target_opacity=}, {line.opacity=}")
|
||||||
|
|
||||||
|
|
||||||
class FrameWriter:
|
class FrameWriter:
|
||||||
|
@ -340,7 +361,8 @@ class Renderer:
|
||||||
self.window.set_handler('on_refresh', self.on_refresh)
|
self.window.set_handler('on_refresh', self.on_refresh)
|
||||||
self.window.set_handler('on_close', self.on_close)
|
self.window.set_handler('on_close', self.on_close)
|
||||||
|
|
||||||
pyglet.gl.glClearColor(81./255, 20/255, 46./255, 0)
|
# Purple background color:
|
||||||
|
pyglet.gl.glClearColor(*AnimConfig.clear_color)
|
||||||
self.fps_display = pyglet.window.FPSDisplay(window=self.window, color=(255,255,255,255))
|
self.fps_display = pyglet.window.FPSDisplay(window=self.window, color=(255,255,255,255))
|
||||||
self.fps_display.label.x = self.window.width - 50
|
self.fps_display.label.x = self.window.width - 50
|
||||||
self.fps_display.label.y = self.window.height - 17
|
self.fps_display.label.y = self.window.height - 17
|
||||||
|
@ -486,7 +508,7 @@ class Renderer:
|
||||||
img = pyglet.image.ImageData(self.frame_size[0], self.frame_size[1], 'RGB', img.tobytes(), pitch=self.frame_size[0] * -1 * channels)
|
img = pyglet.image.ImageData(self.frame_size[0], self.frame_size[1], 'RGB', img.tobytes(), pitch=self.frame_size[0] * -1 * channels)
|
||||||
# don't draw in batch, so that it is the background
|
# don't draw in batch, so that it is the background
|
||||||
self.video_sprite = pyglet.sprite.Sprite(img=img, batch=self.batch_bg)
|
self.video_sprite = pyglet.sprite.Sprite(img=img, batch=self.batch_bg)
|
||||||
self.video_sprite.opacity = 100
|
self.video_sprite.opacity = AnimConfig.video_opacity
|
||||||
except zmq.ZMQError as e:
|
except zmq.ZMQError as e:
|
||||||
# idx = frame.index if frame else "NONE"
|
# idx = frame.index if frame else "NONE"
|
||||||
# logger.debug(f"reuse video frame {idx}")
|
# logger.debug(f"reuse video frame {idx}")
|
||||||
|
|
Loading…
Reference in a new issue