forecast trajectories don't transition, but remain and fade out

This commit is contained in:
Ruben van de Ven 2024-11-05 13:45:20 +01:00
parent e837617e39
commit 9871848407
2 changed files with 65 additions and 45 deletions

View file

@ -97,8 +97,6 @@ class Track:
@dataclass @dataclass
class Frame: class Frame:
index: int index: int

View file

@ -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([])
if len(self.pred_shapes[a]) > (len(drawn_predictions) +1): # for a, drawn_predictions in enumerate(self.drawn_predictions):
self.pred_shapes[a] = self.pred_shapes[a][:len(drawn_predictions)] # if len(self.pred_shapes) <= a:
# self.pred_shapes.append([])
# for i, pos in drawn_predictions.enumerate(): # if len(self.pred_shapes[a]) > (len(drawn_predictions) +1):
for ci in range(0, len(drawn_predictions)): # self.pred_shapes[a] = self.pred_shapes[a][:len(drawn_predictions)]
if ci == 0:
x, y = [int(p) for p in self.drawn_positions[-1]]
else:
x, y = [int(p) for p in drawn_predictions[ci-1]]
x2, y2 = [int(p) for p in drawn_predictions[ci]] # # for i, pos in drawn_predictions.enumerate():
# for ci in range(0, len(drawn_predictions)):
# if ci == 0:
# x, y = [int(p) for p in self.drawn_positions[-1]]
# else:
# x, y = [int(p) for p in drawn_predictions[ci-1]]
y, y2 = self.renderer.window.height - y, self.renderer.window.height - y2 # x2, y2 = [int(p) for p in drawn_predictions[ci]]
# color = [255,0,0]
# print(x,y,x2,y2,color)
if ci >= len(self.pred_shapes[a]): # y, y2 = self.renderer.window.height - y, self.renderer.window.height - y2
# TODO: add color2 # # color = [255,0,0]
line = self.renderer.gradientLine(x, y, x2, y2, 3, color, color, batch=self.renderer.batch_anim) # # print(x,y,x2,y2,color)
line.opacity = 5
self.pred_shapes[a].append(line)
else: # if ci >= len(self.pred_shapes[a]):
line = self.pred_shapes[a][ci-1] # # TODO: add color2
line.x, line.y = x, y # line = self.renderer.gradientLine(x, y, x2, y2, 3, color, color, batch=self.renderer.batch_anim)
line.x2, line.y2 = x2, y2 # line.opacity = 5
line.color = color # self.pred_shapes[a].append(line)
decay = (16/ci) if ci else 16
half = len(drawn_predictions) / 2 # else:
if ci < half: # line = self.pred_shapes[a][ci-1]
target_opacity = 180 # line.x, line.y = x, y
else: # line.x2, line.y2 = x2, y2
target_opacity = (1 - ((ci - half) / half)) * 180 # line.color = color
line.opacity = int(exponentialDecay(line.opacity, target_opacity, decay, dt)) # decay = (16/ci) if ci else 16
# half = len(drawn_predictions) / 2
# if ci < half:
# target_opacity = 180
# else:
# target_opacity = (1 - ((ci - half) / half)) * 180
# 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}")