From 655c75be3eda444dfc2f975fc7b441503434ff59 Mon Sep 17 00:00:00 2001 From: bav6096 <benedikt.deike@informatik.uni-hamburg.de> Date: Wed, 8 Dec 2021 05:05:15 +0100 Subject: [PATCH] added parts of second expression --- CMakeLists.txt | 2 + scripts/build_state_cycle.py | 26 +++++ scripts/build_still_ensemble.py | 0 scripts/reset_display.py | 0 scripts/write.py | 24 ++++ src/visualising/communication/arduino.py | 13 ++- src/visualising/expression/artificial.py | 14 +++ .../expression/{expression.py => emotion.py} | 20 +--- src/visualising/expression/library/A.txt | 2 + src/visualising/expression/library/B.txt | 2 + src/visualising/expression/library/C.txt | 2 + src/visualising/expression/library/D.txt | 2 + src/visualising/expression/library/E.txt | 2 + src/visualising/expression/library/G.txt | 2 + src/visualising/expression/library/H.txt | 2 + src/visualising/expression/library/I.txt | 2 + src/visualising/expression/library/J.txt | 2 + src/visualising/expression/library/L.txt | 2 + src/visualising/expression/library/O.txt | 2 + src/visualising/expression/tool.py | 104 +++++++++++++----- 20 files changed, 174 insertions(+), 51 deletions(-) create mode 100755 scripts/build_state_cycle.py mode change 100644 => 100755 scripts/build_still_ensemble.py mode change 100644 => 100755 scripts/reset_display.py create mode 100755 scripts/write.py create mode 100644 src/visualising/expression/artificial.py rename src/visualising/expression/{expression.py => emotion.py} (74%) mode change 100755 => 100644 create mode 100644 src/visualising/expression/library/A.txt create mode 100644 src/visualising/expression/library/B.txt create mode 100644 src/visualising/expression/library/C.txt create mode 100644 src/visualising/expression/library/D.txt create mode 100644 src/visualising/expression/library/E.txt create mode 100644 src/visualising/expression/library/G.txt create mode 100644 src/visualising/expression/library/H.txt create mode 100644 src/visualising/expression/library/I.txt create mode 100644 src/visualising/expression/library/J.txt create mode 100644 src/visualising/expression/library/L.txt create mode 100644 src/visualising/expression/library/O.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index 2e27b75..a9d3016 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -163,6 +163,8 @@ catkin_install_python(PROGRAMS scripts/play_animation.py scripts/reset_display.py scripts/build_still_ensemble.py + scripts/build_state_cycle.py + scripts/write.py DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} ) diff --git a/scripts/build_state_cycle.py b/scripts/build_state_cycle.py new file mode 100755 index 0000000..c932bf0 --- /dev/null +++ b/scripts/build_state_cycle.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python + +import argparse + +from visualising.expression.tool import Tool +from visualising.communication.arduino import Arduino +from visualising.communication.channel.connection import Connection + +parser = argparse.ArgumentParser(description="script to play an animation") +parser.add_argument("-p", "--port", help="port to which the Arduino is connected", type=str, default="/dev/ttyUSB0") +parser.add_argument("-b", "--baud", help="baud rate of the connection", type=int, default=57600) +parser.add_argument("-t", "--time", help="time between ensembles", type=int, default=100) +args = vars(parser.parse_args()) + +port = args["port"] +baud = args["baud"] +time = args["time"] + +color = [10, 10, 10] + +arduino = Arduino(Connection(port, baud)) + +states = [0.4, 1, 0.2, 0.3, 0.9, 0.7] +ensemble = Tool.build_state_cycle(states) + +arduino.stream_animation(Tool.highlight(ensemble, states, 4)) diff --git a/scripts/build_still_ensemble.py b/scripts/build_still_ensemble.py old mode 100644 new mode 100755 diff --git a/scripts/reset_display.py b/scripts/reset_display.py old mode 100644 new mode 100755 diff --git a/scripts/write.py b/scripts/write.py new file mode 100755 index 0000000..ec35159 --- /dev/null +++ b/scripts/write.py @@ -0,0 +1,24 @@ +#!/usr/bin/env python + +import argparse + +from visualising.expression.tool import Tool +from visualising.communication.arduino import Arduino +from visualising.communication.illustration.animation import Animation +from visualising.communication.channel.connection import Connection + +parser = argparse.ArgumentParser(description="script to play an animation") +parser.add_argument("-p", "--port", help="port to which the Arduino is connected", type=str, default="/dev/ttyUSB0") +parser.add_argument("-b", "--baud", help="baud rate of the connection", type=int, default=57600) +parser.add_argument("-t", "--time", help="time between ensembles", type=int, default=100) +args = vars(parser.parse_args()) + +port = args["port"] +baud = args["baud"] +time = args["time"] + +arduino = Arduino(Connection(port, baud)) + +animation = Tool.write("HALLO") + +arduino.stream_animation(Animation(animation, time, 1)) diff --git a/src/visualising/communication/arduino.py b/src/visualising/communication/arduino.py index f07fa4e..0bfaf9b 100755 --- a/src/visualising/communication/arduino.py +++ b/src/visualising/communication/arduino.py @@ -64,11 +64,16 @@ class Arduino: if time.time() > curr_time + playback_time * 10: raise ArduinoException("Successful playback of animation can't be confirmed!") - # Streams an entities to the Arduino. For this purpose, two frames_library of - # the entities are repeatedly sent to the Arduino. The Arduino plays - # the received frames_library and then confirms the playback, whereupon new - # frames_library are sent. + # Streams an animation to the Arduino. For this purpose, one ensemble of + # the animation is repeatedly sent to the Arduino. The Arduino plays + # the received ensemble and then confirms the playback, whereupon a new + # ensemble is sent. def stream_animation(self, animation): for _ in range(animation.num_iter): for ensemble in animation.ensembles: self.play_animation(Animation([ensemble], animation.ensemble_time, 1)) + + # Streams consecutively animations to the Arduino. + def stream_multiple_animations(self, animation_list): + for animation in animation_list: + self.stream_animation(animation) diff --git a/src/visualising/expression/artificial.py b/src/visualising/expression/artificial.py new file mode 100644 index 0000000..bc73772 --- /dev/null +++ b/src/visualising/expression/artificial.py @@ -0,0 +1,14 @@ +import time +import rospy +import numpy as np + +from visualising.expression.tool import Tool + +class State: + def __init__(self, arduino): + self.arduino = arduino + self.playback_start = 0 + + def react(self, state): + if len(state[1]) > 16: + rospy.logwarn("Only displaying the first 16 metric aggregations!") diff --git a/src/visualising/expression/expression.py b/src/visualising/expression/emotion.py old mode 100755 new mode 100644 similarity index 74% rename from src/visualising/expression/expression.py rename to src/visualising/expression/emotion.py index 3234035..bb37410 --- a/src/visualising/expression/expression.py +++ b/src/visualising/expression/emotion.py @@ -1,5 +1,4 @@ import time -import numpy as np from visualising.expression.tool import Tool @@ -9,17 +8,10 @@ class Emotion: self.arduino = arduino self.playback_start = 0 - @staticmethod - def state_to_color(state): - red = np.array([25, 0, 0]) - white = np.array([25, 25, 25]) - - return (1 - state) * white + state * red - def react(self, state): if time().time - playback_start > 5: - color = Emotion.state_to_color(state[0]) + color = Tool.state_to_color(state[0], [25, 25, 25], [25, 0, 0]) if state[0] > 0.7: self.happy(color) @@ -43,13 +35,3 @@ class Emotion: ensembles = Tool.create_ensembles("expression_angry.txt") self.arduino.stream_animation(Tool.build_still_ensemble_parallel(ensembles[0], 50, color)) self.playback_start = time.time() - - -class State: - def __init__(self, arduino): - self.arduino = arduino - self.playback_start = 0 - - def react(self, state): - pass - diff --git a/src/visualising/expression/library/A.txt b/src/visualising/expression/library/A.txt new file mode 100644 index 0000000..23b7df9 --- /dev/null +++ b/src/visualising/expression/library/A.txt @@ -0,0 +1,2 @@ +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +10,10,10,10,10,10,10,10,10,10,10,10,10,0,0,10,10,10,10,10,10,0,0,0,0,0,0,0,0,0,10,10,10,10,10,10,10,0,0,10,10,10,10,10,10,10,10,10 diff --git a/src/visualising/expression/library/B.txt b/src/visualising/expression/library/B.txt new file mode 100644 index 0000000..e0f20c8 --- /dev/null +++ b/src/visualising/expression/library/B.txt @@ -0,0 +1,2 @@ +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,0,0,10,10,10,10,10,10,10,10,10,10,0,0,10,10,10,10,10,10,10,10,10 \ No newline at end of file diff --git a/src/visualising/expression/library/C.txt b/src/visualising/expression/library/C.txt new file mode 100644 index 0000000..ee479a4 --- /dev/null +++ b/src/visualising/expression/library/C.txt @@ -0,0 +1,2 @@ +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,0,0,0,0,0,0,10,10,10,10,10,10,10,10,10 \ No newline at end of file diff --git a/src/visualising/expression/library/D.txt b/src/visualising/expression/library/D.txt new file mode 100644 index 0000000..30179ed --- /dev/null +++ b/src/visualising/expression/library/D.txt @@ -0,0 +1,2 @@ +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +10,10,10,10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,0,0,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10 \ No newline at end of file diff --git a/src/visualising/expression/library/E.txt b/src/visualising/expression/library/E.txt new file mode 100644 index 0000000..11152ec --- /dev/null +++ b/src/visualising/expression/library/E.txt @@ -0,0 +1,2 @@ +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +10,0,0,10,0,0,10,0,0,10,0,0,10,0,0,10,0,0,10,0,0,10,0,0,10,0,0,10,0,0,0,0,0,0,0,0,10,10,10,10,0,0,10,0,0,10,0,0 \ No newline at end of file diff --git a/src/visualising/expression/library/G.txt b/src/visualising/expression/library/G.txt new file mode 100644 index 0000000..8023585 --- /dev/null +++ b/src/visualising/expression/library/G.txt @@ -0,0 +1,2 @@ +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,0,0,0,0,0,0,0,0,10,10,10,10,10,10 \ No newline at end of file diff --git a/src/visualising/expression/library/H.txt b/src/visualising/expression/library/H.txt new file mode 100644 index 0000000..7fc24e6 --- /dev/null +++ b/src/visualising/expression/library/H.txt @@ -0,0 +1,2 @@ +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +0,0,0,0,0,0,10,10,10,10,10,10,10,0,0,10,10,10,10,10,10,0,0,0,0,0,0,0,0,0,10,10,10,10,10,10,10,0,0,10,10,10,10,10,10,0,0,0 \ No newline at end of file diff --git a/src/visualising/expression/library/I.txt b/src/visualising/expression/library/I.txt new file mode 100644 index 0000000..42bf303 --- /dev/null +++ b/src/visualising/expression/library/I.txt @@ -0,0 +1,2 @@ +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +10,0,0,10,10,10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,10,10,10,0,0,10,10,10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,10,10 \ No newline at end of file diff --git a/src/visualising/expression/library/J.txt b/src/visualising/expression/library/J.txt new file mode 100644 index 0000000..dc32ec0 --- /dev/null +++ b/src/visualising/expression/library/J.txt @@ -0,0 +1,2 @@ +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +1,1,1,1,1,1,10,10,10,0,0,0,0,0,0,0,0,0,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,1,1,1 \ No newline at end of file diff --git a/src/visualising/expression/library/L.txt b/src/visualising/expression/library/L.txt new file mode 100644 index 0000000..3046ae8 --- /dev/null +++ b/src/visualising/expression/library/L.txt @@ -0,0 +1,2 @@ +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,0,0,10,10,10,10,10,10,10,10,10,0,0,0,0,0,0,0,0,0,0,0,0 \ No newline at end of file diff --git a/src/visualising/expression/library/O.txt b/src/visualising/expression/library/O.txt new file mode 100644 index 0000000..29d6d8d --- /dev/null +++ b/src/visualising/expression/library/O.txt @@ -0,0 +1,2 @@ +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10 \ No newline at end of file diff --git a/src/visualising/expression/tool.py b/src/visualising/expression/tool.py index 8d28923..b635235 100644 --- a/src/visualising/expression/tool.py +++ b/src/visualising/expression/tool.py @@ -1,6 +1,7 @@ #!/usr/bin/env python import re +import numpy as np import importlib.resources from visualising.communication.illustration.animation import Animation @@ -81,6 +82,36 @@ class Tool: ensembles = Tool.create_ensembles(filename) return Animation(ensembles, ensemble_time, iterations) + @staticmethod + def create_empty_ensemble(): + l_pixels = [] + r_pixels = [] + for _ in range(16): + l_pixels.append(Pixel(0, 0, 0)) + r_pixels.append(Pixel(0, 0, 0)) + + return Ensemble(Frame(l_pixels), Frame(r_pixels)) + + @staticmethod + def set_pixel_color(ensemble, pixel, r, g, b): + if not 0 <= pixel <= 31: + raise ValueError("Pixel index must be an integer between 0 and 31!") + + if pixel < 16: + ensemble.l_frame.adjust_color(pixel, r, g, b) + else: + pixel = pixel - 16 + ensemble.r_frame.adjust_color(pixel, r, g, b) + + return ensemble + + @staticmethod + def state_to_color(state, start_color, end_color): + if not 0 <= state <= 1: + raise ValueError("State must be a value between 0 and 1!") + + return (1 - state) * np.array(start_color) + state * np.array(end_color) + @staticmethod def build_still_ensemble(still_ensemble, ensemble_time, color): r = color[0] @@ -150,40 +181,57 @@ class Tool: return Animation(ensembles, ensemble_time, 1) @staticmethod - def merge_frames(l_frames, r_frames): - if len(l_frames) != len(r_frames): - raise ValueError("Merging different number of frames_library not allowed!") - - merged_frames = [] - for l_frame, r_frame in zip(l_frames, r_frames): - merged_frames = merged_frames + l_frame - merged_frames = merged_frames + r_frame + def build_state_cycle(state_vector): + ensemble = Tool.create_empty_ensemble() + pixel = 0 + for state in state_vector: + color = Tool.state_to_color(state, [0, 50, 0], [50, 0, 0]) + ensemble = Tool.set_pixel_color(ensemble, pixel, color[0], color[1], color[2]) + pixel = pixel + 1 - return merged_frames + return ensemble @staticmethod - def concatenate_frames(start, end): - return start.extend(end) + def highlight(ensemble, states, number): + number = min(len(states), number) + highlight = sorted(zip(states, range(len(states))), reverse=True)[:number] - @staticmethod - def create_empty_ensemble(): - l_pixels = [] - r_pixels = [] - for _ in range(16): - l_pixels.append(Pixel(0, 0, 0)) - r_pixels.append(Pixel(0, 0, 0)) + ensembles = [ensemble] + for tuple in highlight: + empty = Tool.create_empty_ensemble() + for i in range(16): + if ensemble.l_frame.is_colored(i): - return Ensemble(Frame(l_pixels), Frame(r_pixels)) + r = ensemble.l_frame.pixels[i].r + g = ensemble.l_frame.pixels[i].g + b = ensemble.l_frame.pixels[i].b + + off = [0, 0, 0] + + if tuple[1] != i: + empty = Tool.set_pixel_color(empty, i, off[0], off[1], off[2]) + else: + empty = Tool.set_pixel_color(empty, i, r, g, b) + + ensembles.append(empty) + ensembles = ensembles + Tool.write("HALLO") + ensembles.append(ensemble) + + ensembles.append(Tool.create_empty_ensemble()) + + return Animation(ensembles, 500, 1) @staticmethod - def set_pixel_color(ensemble, pixel, r, g, b): - if not 0 <= pixel <= 31: - raise ValueError("Pixel index must be an integer between 0 and 31!") + def write(text): + if not text.isalpha(): + raise ValueError("Text must contain only alphabetic characters!") - if pixel < 16: - ensemble.l_frame.adjust_color(pixel, r, g, b) - else: - pixel = pixel - 16 - ensemble.r_frame.adjust_color(pixel, r, g, b) + text = text.upper() - return ensemble + ensembles = [] + for char in text: + file = char + ".txt" + ensembles = ensembles + Tool.create_ensembles(file) + ensembles.append(Tool.create_empty_ensemble()) + + return ensembles -- GitLab