diff --git a/bitbots_misc/bitbots_education/.gitignore b/bitbots_misc/bitbots_education/.gitignore new file mode 100644 index 000000000..89f9ac04a --- /dev/null +++ b/bitbots_misc/bitbots_education/.gitignore @@ -0,0 +1 @@ +out/ diff --git a/bitbots_misc/bitbots_education/bitbots_education/__init__.py b/bitbots_misc/bitbots_education/bitbots_education/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/bitbots_misc/bitbots_education/bitbots_education/app.py b/bitbots_misc/bitbots_education/bitbots_education/app.py new file mode 100644 index 000000000..8be31657f --- /dev/null +++ b/bitbots_misc/bitbots_education/bitbots_education/app.py @@ -0,0 +1,73 @@ +import csv +import os +import time + +from ament_index_python import get_package_share_directory +from flask import Flask, render_template, request + +template_dir = os.path.join(get_package_share_directory("bitbots_education"), "templates") +static_folder = os.path.join(get_package_share_directory("bitbots_education"), "static") +csv_file_path = os.path.realpath("logs.csv") + +app = Flask(__name__, template_folder=template_dir, static_folder=static_folder) + + +def write_csv(vp, page, button, status): + file_exists = os.path.isfile(csv_file_path) + with open(csv_file_path, "a+", newline="") as file: + writer = csv.writer(file) + # Kopfzeile nur schreiben, wenn die Datei neu ist + if not file_exists or os.stat("logs.csv").st_size == 0: + writer.writerow(["VP", "Page", "Button", "Status", "Timestamp"]) + curr_time = time.time() + writer.writerow([vp, page, button, status, curr_time]) + + +def vp_track(page, button, status): + username = request.cookies.get("vp_number") + if username is not None: + write_csv(username, page, button, status) + + +@app.route("/") +def index(): + vp_track("dashboard", "", "") + dashboard = "pages/dashboard.html" + return render_template(dashboard, logging=bool(request.args.get("logging", False))) + + +@app.route("/imu") +def imu(): + vp_track("imu", "", "") + return render_template("pages/imu.html") + + +@app.route("/vision") +def vision(): + vp_track("vision", "", "") + return render_template("pages/vision.html") + + +@app.route("/motors") +def motors(): + vp_track("motors", "", "") + return render_template("pages/motors.html") + + +@app.route("/behavior") +def behavior(): + vp_track("behavior", "", "") + return render_template("pages/behavior.html") + + +@app.route("/logs") +def logs(): + page = request.args.get("page") + button = request.args.get("button") + status = request.args.get("status") + vp_track(page[1:], button, status) + return ("", 204) + + +def main(): + app.run(host="0.0.0.0", port=8000) diff --git a/bitbots_misc/bitbots_education/launch/education.launch b/bitbots_misc/bitbots_education/launch/education.launch new file mode 100644 index 000000000..9d18d2147 --- /dev/null +++ b/bitbots_misc/bitbots_education/launch/education.launch @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/bitbots_misc/bitbots_education/launch/education_simulation.launch b/bitbots_misc/bitbots_education/launch/education_simulation.launch new file mode 100644 index 000000000..44222759b --- /dev/null +++ b/bitbots_misc/bitbots_education/launch/education_simulation.launch @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/bitbots_misc/bitbots_education/package.xml b/bitbots_misc/bitbots_education/package.xml new file mode 100644 index 000000000..4df28a069 --- /dev/null +++ b/bitbots_misc/bitbots_education/package.xml @@ -0,0 +1,19 @@ + + + + bitbots_education + 0.0.0 + A web interface that shows live data in easy to understand visualizations for public events. + root + MIT + + web_video_server + rosbridge_suite + python3-jinja2 + python3-flask + python3-pytest + + + ament_python + + diff --git a/bitbots_misc/bitbots_education/resource/bitbots_education b/bitbots_misc/bitbots_education/resource/bitbots_education new file mode 100644 index 000000000..e69de29bb diff --git a/bitbots_misc/bitbots_education/scripts/.gitignore b/bitbots_misc/bitbots_education/scripts/.gitignore new file mode 100644 index 000000000..29a7166e8 --- /dev/null +++ b/bitbots_misc/bitbots_education/scripts/.gitignore @@ -0,0 +1,2 @@ +*.csv + diff --git a/bitbots_misc/bitbots_education/setup.cfg b/bitbots_misc/bitbots_education/setup.cfg new file mode 100644 index 000000000..70c036156 --- /dev/null +++ b/bitbots_misc/bitbots_education/setup.cfg @@ -0,0 +1,4 @@ +[develop] +script_dir=$base/lib/bitbots_education +[install] +install_scripts=$base/lib/bitbots_education diff --git a/bitbots_misc/bitbots_education/setup.py b/bitbots_misc/bitbots_education/setup.py new file mode 100644 index 000000000..755789669 --- /dev/null +++ b/bitbots_misc/bitbots_education/setup.py @@ -0,0 +1,40 @@ +import glob +import os + +from setuptools import find_packages, setup + +package_name = "bitbots_education" + + +def generate_data_files(share_path, directory): + data_files = [] + + for path, _, files in os.walk(directory): + p = share_path + path + list_entry = (p, [os.path.join(path, f) for f in files if not f.startswith(".")]) + data_files.append(list_entry) + + return data_files + + +setup( + name=package_name, + data_files=[ + ("share/ament_index/resource_index/packages", ["resource/" + package_name]), + ("share/" + package_name, ["package.xml"]), + ("share/" + package_name + "/launch", glob.glob("launch/*.launch")), + ] + + generate_data_files("share/" + package_name + "/", "templates/") + + generate_data_files("share/" + package_name + "/", "static/"), + version="0.0.0", + packages=find_packages(exclude=["test"]), + install_requires=["setuptools"], + zip_safe=True, + license="MIT", + tests_require=["pytest"], + entry_points={ + "console_scripts": [ + "webserver = bitbots_education.app:main", + ], + }, +) diff --git a/bitbots_misc/bitbots_education/static/abstract_robot.svg b/bitbots_misc/bitbots_education/static/abstract_robot.svg new file mode 100644 index 000000000..fcb47a275 --- /dev/null +++ b/bitbots_misc/bitbots_education/static/abstract_robot.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/bitbots_misc/bitbots_education/static/abstract_robot.webp b/bitbots_misc/bitbots_education/static/abstract_robot.webp new file mode 100644 index 000000000..a22e1fb11 Binary files /dev/null and b/bitbots_misc/bitbots_education/static/abstract_robot.webp differ diff --git a/bitbots_misc/bitbots_education/static/bitBot_color.svg b/bitbots_misc/bitbots_education/static/bitBot_color.svg new file mode 100644 index 000000000..7e6063d00 --- /dev/null +++ b/bitbots_misc/bitbots_education/static/bitBot_color.svg @@ -0,0 +1,1043 @@ + + + + + BitBot + + + + image/svg+xml + + BitBot + 2011 + + + Timon Giese + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/bitbots_misc/bitbots_education/static/bitBot_whiteboard.svg b/bitbots_misc/bitbots_education/static/bitBot_whiteboard.svg new file mode 100644 index 000000000..5be8a45ef --- /dev/null +++ b/bitbots_misc/bitbots_education/static/bitBot_whiteboard.svg @@ -0,0 +1,991 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Strategie: + + + diff --git a/bitbots_misc/bitbots_education/static/camera.png b/bitbots_misc/bitbots_education/static/camera.png new file mode 100644 index 000000000..98960722a Binary files /dev/null and b/bitbots_misc/bitbots_education/static/camera.png differ diff --git a/bitbots_misc/bitbots_education/static/expand-collapse.svg b/bitbots_misc/bitbots_education/static/expand-collapse.svg new file mode 100644 index 000000000..f34809c99 --- /dev/null +++ b/bitbots_misc/bitbots_education/static/expand-collapse.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/bitbots_misc/bitbots_education/static/imunew.png b/bitbots_misc/bitbots_education/static/imunew.png new file mode 100644 index 000000000..5b94fe307 Binary files /dev/null and b/bitbots_misc/bitbots_education/static/imunew.png differ diff --git a/bitbots_misc/bitbots_education/static/motor.png b/bitbots_misc/bitbots_education/static/motor.png new file mode 100644 index 000000000..8f7b2cb89 Binary files /dev/null and b/bitbots_misc/bitbots_education/static/motor.png differ diff --git a/bitbots_misc/bitbots_education/templates/base.html b/bitbots_misc/bitbots_education/templates/base.html new file mode 100644 index 000000000..7b961b334 --- /dev/null +++ b/bitbots_misc/bitbots_education/templates/base.html @@ -0,0 +1,185 @@ + + + + + + + + + + + + + + + + +
+ +
+
+ {% block content %}{% endblock %} +
+
+ Uicons by Flaticon +
+
+
+
+ {% block icons %}{% endblock %} +
+
+ + diff --git a/bitbots_misc/bitbots_education/templates/components/behavior_stack.html b/bitbots_misc/bitbots_education/templates/components/behavior_stack.html new file mode 100644 index 000000000..273e20c07 --- /dev/null +++ b/bitbots_misc/bitbots_education/templates/components/behavior_stack.html @@ -0,0 +1,83 @@ +{% macro behavior_stack_component() %} + + + + +
+
+
+
+
+
+
+ +
+ +{% endmacro %} diff --git a/bitbots_misc/bitbots_education/templates/components/behavior_tree.html b/bitbots_misc/bitbots_education/templates/components/behavior_tree.html new file mode 100644 index 000000000..5bf1dbf71 --- /dev/null +++ b/bitbots_misc/bitbots_education/templates/components/behavior_tree.html @@ -0,0 +1,176 @@ +{% macro behavior_tree_component() %} + + + + + +
+
+ +
+
+ +{% endmacro %} diff --git a/bitbots_misc/bitbots_education/templates/components/behavior_tree_minimal.html b/bitbots_misc/bitbots_education/templates/components/behavior_tree_minimal.html new file mode 100644 index 000000000..1b7f97d22 --- /dev/null +++ b/bitbots_misc/bitbots_education/templates/components/behavior_tree_minimal.html @@ -0,0 +1,242 @@ +{% macro behavior_tree_minimal_component() %} + + + + + +
+
+ +
+
+ +{% endmacro %} diff --git a/bitbots_misc/bitbots_education/templates/components/current_action.html b/bitbots_misc/bitbots_education/templates/components/current_action.html new file mode 100644 index 000000000..e73975ff2 --- /dev/null +++ b/bitbots_misc/bitbots_education/templates/components/current_action.html @@ -0,0 +1,49 @@ +{% macro current_action_component() %} + + + +
+

+

+ +

+
+{% endmacro %} diff --git a/bitbots_misc/bitbots_education/templates/components/icon_footer.html b/bitbots_misc/bitbots_education/templates/components/icon_footer.html new file mode 100644 index 000000000..25ac47fc2 --- /dev/null +++ b/bitbots_misc/bitbots_education/templates/components/icon_footer.html @@ -0,0 +1,48 @@ +{% macro icons(site) %} +
+ + + {% if site == 'dashboard' %} + + {% else %} + + {% endif %} + + + + {% if site == 'imu' %} + + {% else %} + + {% endif %} + + + + {% if site == 'vision' %} + + {% else %} + + {% endif %} + + + + {% if site == 'heat' %} + + {% else %} + + + + + + {% endif %} + + + + {% if site == 'behavior' %} + + {% else %} + + {% endif %} + +
+{% endmacro %} diff --git a/bitbots_misc/bitbots_education/templates/components/imu.html b/bitbots_misc/bitbots_education/templates/components/imu.html new file mode 100644 index 000000000..d6f08b7be --- /dev/null +++ b/bitbots_misc/bitbots_education/templates/components/imu.html @@ -0,0 +1,65 @@ +{% macro imu_component() %} + + + +
+ +
+{% endmacro %} diff --git a/bitbots_misc/bitbots_education/templates/components/motor_heat.html b/bitbots_misc/bitbots_education/templates/components/motor_heat.html new file mode 100644 index 000000000..f1717090d --- /dev/null +++ b/bitbots_misc/bitbots_education/templates/components/motor_heat.html @@ -0,0 +1,121 @@ +{% macro motor_heat_component(max_temperature) %} + + + +{% if max_temperature == True %} +
+ °C +
+{% else %} +
+
+ +
+
+ + +
+
+ °C +
+ + +
+
+
+
+ +
+ °C +
+
+
+{% endif %} +{% endmacro %} + diff --git a/bitbots_misc/bitbots_education/templates/components/textbox.html b/bitbots_misc/bitbots_education/templates/components/textbox.html new file mode 100644 index 000000000..f28be5ee0 --- /dev/null +++ b/bitbots_misc/bitbots_education/templates/components/textbox.html @@ -0,0 +1,43 @@ +{% macro textbox(label, content, style, top, bottom) %} + + +
+ +

{{ content }}

+ + + +
+ + +{% endmacro %} diff --git a/bitbots_misc/bitbots_education/templates/components/vision.html b/bitbots_misc/bitbots_education/templates/components/vision.html new file mode 100644 index 000000000..8a9bc1b98 --- /dev/null +++ b/bitbots_misc/bitbots_education/templates/components/vision.html @@ -0,0 +1,15 @@ +{% macro vision_component() %} + + +
+ +
+{% endmacro %} diff --git a/bitbots_misc/bitbots_education/templates/pages/behavior.html b/bitbots_misc/bitbots_education/templates/pages/behavior.html new file mode 100644 index 000000000..d2a19b989 --- /dev/null +++ b/bitbots_misc/bitbots_education/templates/pages/behavior.html @@ -0,0 +1,105 @@ +{% import "components/current_action.html" as current_action_components %} +{% import "components/behavior_stack.html" as behavior_stack_component %} +{% import "components/behavior_tree.html" as behavior_tree_component %} +{% import "components/behavior_tree_minimal.html" as behavior_tree_minimal %} +{% import "components/textbox.html" as components %} +{% import "components/icon_footer.html" as icon_components %} + + +{% extends "base.html" %} + +{% block banner %}Verhalten{% endblock %} + +{% block content %} + +
+
+
+ + +
+
+ +
+ {{ behavior_stack_component.behavior_stack_component() }} +
+
+ {{ behavior_tree_minimal.behavior_tree_minimal_component() }} +
+ +
+
+
+
+
+
Auswahl
+
+
+
+
+
+
Aktion
+
+
+
+
+
+
Option
+
+
+
+
+
+
Abwägung
+
+
+ {{ components.textbox("Warum ändern sich die Boxen und wieso haben sie unterschiedliche Farben?", + "Jede Box steht für eine Entscheidung oder eine Aktion, die der Roboter macht. + Dabei macht er meist viele unterschiedliche Abwägungen (blaue Boxen), bis er sich am Ende für eine Aktion entscheidet, + die er dann ausführt (helle Box). Zusätzlich steht unter jeder Entscheidung neben dem Pfeil nach unten, wofür der Roboter sich entschieden hat. + Da der Roboter während des Spiels in unterschiedliche Situationen kommt, ändern sich seine Entscheidungen dementsprechend. + Es gibt auch eine alternative Verhaltensbaum-Ansicht, in die durch einen Klick oben auf der Leiste gewechselt werden kann. + Dort sind die Entscheidungen in einer Baumstruktur zu sehen, die sich aus den Abwägungen ergibt. + Der Baum ist anfangs noch eingeklappt und kann durch Klicken auf die blauen Abwägungen erweitert werden. + Zusätzlich stoppt und startet der Button unter der Aktion des Stapels den Fluss an Entscheidungen. ", true, true, false) }} +
+ +
+ {{ components.textbox("Vergleich zum Menschen", "Das Verhalten ist ähnlich zur Entscheidungsfindung des Menschen, + wobei durch kleine Entscheidungen verschiedene Einflüsse abgewogen werden, bis sich der Roboter für eine endgültige Aktion entscheidet.", true, true, false)}} + + {{ components.textbox("Nutzen im Roboter", "Das Verhalten steuert, wo der Roboter hinläuft und was er als Nächstes tut. + Hier sind Strategien für das Spiel gespeichert, also Spielzüge: wer wann zum Ball stürmt oder als Verteidiger zurückbleibt. + Um diese Entscheidungen treffen zu können, bekommt das Verhalten sehr viele Informationen von anderen Softwarekomponenten, + wie zum Beispiel die Position des Balls aus der Bildverarbeitung.", true, false, true)}} + + {{ components.textbox("Wie funktioniert das Verhalten?", "Im Vergleich zur Bildverarbeitung ist das Verhalten nicht gelernt, + sondern besteht aus vielen Abwägungen ähnlich zu: wenn X, dann Y. Wobei X und Y durch einen Informatiker im Code festgelegt worden sind. + Es gibt verschiedene Strukturen, in denen man diese Abwägungen ordnen kann — darunter endliche Automaten oder Entscheidungsbäume. + Doch die Bit-Bots haben sich eine eigene Struktur überlegt: den Dynamic Stack Decider (kurz DSD, in Deutsch so etwas wie dynamischer Stapel-Entscheider). + Der DSD ist zunächst sehr ähnlich zu einem Entscheidungsbaum. Die Baumstruktur entsteht dabei durch die verschiedenen Antwortmöglichkeiten auf eine Entscheidung, + der ganze Baum ist oben in der Baum-Ansicht zu sehen. Was den DSD nun besonders macht, ist, dass er sich für den + aktuell ausgewählten Pfad für jede Entscheidung Zusatzinformationen merkt, indem er die gemachten Entscheidungen auf einen Stapel legt. Der Stapel ist in der Stapel-Ansicht zu sehen. + Ändert sich nun der Pfad, weil sich eine Entscheidung an einer Stelle aufgrund einer veränderten Spielsituation ändert, + ändert sich auch der ganze Stapel darunter und alles, was sich die Software dort gemerkt hat, wird zurückgesetzt.", false, false, false)}} +
+{% endblock %} + +{% block icons %} + {{ icon_components.icons("behavior") }} +{% endblock %} + diff --git a/bitbots_misc/bitbots_education/templates/pages/dashboard.html b/bitbots_misc/bitbots_education/templates/pages/dashboard.html new file mode 100644 index 000000000..487349098 --- /dev/null +++ b/bitbots_misc/bitbots_education/templates/pages/dashboard.html @@ -0,0 +1,91 @@ +{% import "components/imu.html" as imu_components %} +{% import "components/vision.html" as vision_components %} +{% import "components/current_action.html" as current_action_components %} +{% import "components/textbox.html" as components %} +{% import "components/motor_heat.html" as heat_components %} +{% import "components/icon_footer.html" as icon_components %} + + + +{% extends "base.html" %} + + + +{% block banner %}Hamburg Bit-Bots{% endblock %} + +{% block content %} + +{% if logging %} + +{% endif %} + +{{ components.textbox("Willkommen!", "Klicke auf eine der Boxen oder eines der Icons in der Leiste, um mehr Informationen zu bekommen.", true, true, true) }} + +
+ +
+
+
+ {{ imu_components.imu_component() }} +
+
+

IMU

+
+
+ +
+ {{ vision_components.vision_component() }} +

Bildverarbeitung

+
+
+ +
+
+ {{ heat_components.motor_heat_component(true) }} +
+

Motoren

+
+
+ +
+
+
+ {{ current_action_components.current_action_component() }} +
+
+

Verhalten

+
+
+
+ + + +{% endblock %} + +{% block icons %} + {{ icon_components.icons("dashboard") }} +{% endblock %} + diff --git a/bitbots_misc/bitbots_education/templates/pages/imu.html b/bitbots_misc/bitbots_education/templates/pages/imu.html new file mode 100644 index 000000000..a09e50aa2 --- /dev/null +++ b/bitbots_misc/bitbots_education/templates/pages/imu.html @@ -0,0 +1,46 @@ +{% import "components/imu.html" as imu_components %} +{% import "components/textbox.html" as components %} +{% import "components/icon_footer.html" as icon_components %} + +{% extends "base.html" %} + +{% block banner %}IMU{% endblock %} + +{% block content %} +
+
+
+ {{ imu_components.imu_component() }} +
+
+ {{ components.textbox("Warum wackelt der Bit-Bot da so?", + "Die Abbildung mit dem Roboter visualisiert die Drehgeschwindigkeiten und Beschleunigungen des Roboters. + Diese wurden durch eine inertiale Messeinheit (im Englischen inertial measurement unit, kurz IMU) gemessen. Wenn der echte Roboter also zur Seite kippt, + dann misst die IMU dies und der kleine Bit-Bot hier oben neigt sich ebenfalls.", true, true, false) }} + {{ components.textbox("Vergleich zum Menschen", "Die IMU ist vergleichbar mit dem menschlichen Gleichgewichtssinn.", true, false, false)}} +
+
+ +
+
+

Die blau umkreiste Komponente ist die IMU

+
+ {{ components.textbox("Nutzen im Roboter", "Die Daten, welche die IMU aufnimmt, können zur Laufstabilisierung beitragen. + Kippt der Roboter zu weit in die eine Richtung, kann die Software darauf reagieren und Maßnahmen vornehmen, die ein Fallen verhindern. + Sollte der Roboter zu weit kippen, zeigt das die IMU ebenfalls an und der Roboter kann noch im Fallen darauf reagieren. + Dadurch wird eine möglichst hardwareschonende Landung möglich. Zudem wird sie genutzt, um festzustellen, auf welche + Seite der Roboter gefallen ist und was er machen muss, um wieder aufzustehen.", true, false, true)}} + {{ components.textbox("Wie funktioniert die IMU?", "Unsere IMU besitzt zwei Hauptbestandteile. Das erste ist ein Gyroskop, + welches die Rotationsgeschwindigkeit der IMU misst. Das zweite ist ein Beschleunigungssensor, welcher die Beschleunigung der + IMU in verschiedene Richtungen misst. Meist nimmt eine IMU nicht nur Daten auf, sondern verarbeitet diese auch gleich ein wenig. + Hierbei wird zum Beispiel die Schräglage des Roboters über kurze Zeit durch Integrieren (vereinfacht: Aufsummieren von Werten) des Gyroskops errechnet. + Dabei werden auch kleine Messfehler aufsummiert, welche kurzzeitig wenig Einfluss haben, über lange Zeit das Ergebnis deutlich verändern. + Deshalb wird der Wert über lange Zeit mithilfe der von den Beschleunigungssensoren gemessenen Erdbeschleunigung korrigiert. + ", false, false, false)}} +
+{% endblock %} + +{% block icons %} + {{ icon_components.icons("imu") }} +{% endblock %} + diff --git a/bitbots_misc/bitbots_education/templates/pages/motors.html b/bitbots_misc/bitbots_education/templates/pages/motors.html new file mode 100644 index 000000000..639ef61de --- /dev/null +++ b/bitbots_misc/bitbots_education/templates/pages/motors.html @@ -0,0 +1,47 @@ + +{% import "components/textbox.html" as components %} +{% import "components/motor_heat.html" as heat_components %} +{% import "components/icon_footer.html" as icon_components %} + + +{% extends "base.html" %} + +{% block banner %}Motoren{% endblock %} + +{% block content %} +
+ + {{ heat_components.motor_heat_component(false) }} + + {{ components.textbox("Was sind das für bunte Punkte auf dem Roboter?", "Jeder farbige Punkt zeigt den jeweils wärmsten Motor des Gelenks an. + Je weiter oben die Farbe des Punktes auf der Skala neben dem Roboter dabei ist, desto wärmer ist der wärmste Motor an der Stelle. + Die beiden Werte über und unter der Skala geben an, in welchem Spektrum sich die Temperaturen der Motoren bewegen. + Dabei ist kein Motor kühler als die untere Temperatur oder wärmer als die obere Temperatur.", true, true, false) }} + {{ components.textbox("Vergleich zum Menschen", "Die Motoren sind wie Muskeln, die den Roboter bewegen. Mit der Zeit werden die Motoren durch die Bewegung immer wärmer, + ähnlich dazu, wie uns Menschen beim Sport meist auch wärmer wird. Je wärmer die Motoren werden, desto ungenauer werden sie, + wodurch der Roboter über die Zeit hinweg immer schlechter läuft — ähnlich dazu, wie wir Menschen durch Sport erschöpfter werden.", true, false, false)}} +
+ +

Dieses Motormodell ist aktuell vor allem in den Beinen zu finden.

+
+ {{ components.textbox("Nutzen im Roboter", "Die Motoren führen Befehle aus und fahren die Positionen an, die die Software ihnen vorgibt. + Dabei hat jede Motorposition eine wichtige Aufgabe im Spielgeschehen: Die Motoren in den Beinen bewegen den Roboter über das Spielfeld, + die Motoren in den Armen werden hauptsächlich beim Aufstehen genutzt, und die Motoren im Hals bewegen unaufhörlich die Kamera, damit diese ein möglichst großes + Feld nach wichtigen Informationen absuchen kann.", true, false, true)}} + {{ components.textbox("Wie gut können Roboter laufen?", "Wir Menschen laufen unser Leben lang, + meist auch schon ab sehr jungen Jahren. Einmal gelernt, machen wir die Bewegungsabläufe fast schon automatisch. + Darüber hinaus helfen uns unsere Reflexe bei der Laufstabilisierung, ohne dass wir aktiv etwas entscheiden müssen. + Um nun einen Roboter zum Laufen zu bringen, müssen wir verstehen, welche Bewegungsabläufe wir Menschen beim Laufen machen, + und diese auf den Roboter übertragen — was gar nicht so einfach ist, weil vieles am Laufen, z.B. auch das Gleichgewicht halten, + eher ein unbewusster Prozess ist. Daher ist vor allem das zweibeinige Laufen ein relativ schweres Problem für Roboter bzw. + für herkömmliche Algorithmen. Hier wird dann mit sogenannten Splines gearbeitet, dies sind Kurven zwischen Punkten auf einem Graphen, + die ruckfreie Bewegungsabläufe modellieren. Mittlerweile benutzen viele Roboter bestärkendes Lernen. Hierbei lernt der Roboter das Laufen mehr wie ein Mensch. + Dabei soll der Roboter in einer Simulation versuchen zu laufen: Schafft er dies, wird er belohnt, schafft er es nicht, wird ihm das auch mitgeteilt, + und er versucht einen neuen Ansatz. Meist ist das Laufenlernen hier auch ein Prozess, der über viele Wiederholungen stattfindet, + dann aber auch bessere Ergebnisse liefert als herkömmliche Algorithmen.", false, false, false)}} +
+{% endblock %} + +{% block icons %} +{{ icon_components.icons("heat") }} +{% endblock %} diff --git a/bitbots_misc/bitbots_education/templates/pages/vision.html b/bitbots_misc/bitbots_education/templates/pages/vision.html new file mode 100644 index 000000000..c35ae2b4d --- /dev/null +++ b/bitbots_misc/bitbots_education/templates/pages/vision.html @@ -0,0 +1,66 @@ +{% import "components/vision.html" as vision_components %} +{% import "components/textbox.html" as components %} +{% import "components/icon_footer.html" as icon_components %} + +{% extends "base.html" %} + +{% block banner %}Bildverarbeitung{% endblock %} + +{% block content %} + +{{ vision_components.vision_component() }} +
+
+
+
+
+
+
Ball
+
+
+
+
+
+
Linien
+
+
+
+
+
+
Roboter
+
+
+
+
+ {{ components.textbox( + "Was ist das für ein Kreis um dem Ball herum?", + "Das hier ist nicht einfach nur der Live-Stream der Kamera des Roboters. Er beinhaltet zudem Markierungen der Dinge, + die der Roboter in dem Bild zu sehen glaubt. Dabei werden Bälle mit einem grünen Kreis versehen, andere Roboter eingerahmt und Linien in Blau markiert.", + true, true, false) }} + {{ components.textbox("Vergleich zum Menschen", "Die Bilderkennung des Roboters gleicht der Objekterkennung des Menschen. + Sie schaut auf ein Bild und sagt: An der Stelle ist ein Ball. Ähnlich wie beim Menschen wird sie nicht etwa manuell einprogrammiert, + sondern durch das Betrachten von vielen Bildern erlernt. +", true, false, false)}} +
+ +

Die aktuelle Kamera des Roboters. Die dunkle "Frisur" hilft bei der Kühlung der Kamera.

+
+ {{ components.textbox("Nutzen im Roboter", "Viele Komponenten des Roboters benutzen die Erkenntnisse aus der Bildverarbeitung: + Das Wissen über die Position des Balls ist für Verhaltensentscheidungen sehr wichtig, erkannte Feldlinien dienen zur Orientierung + auf dem Feld und erkannte Roboter werden in der Strategie sowie der Pfadplanung berücksichtigt — Letzteres vor allem, damit es möglichst wenig Zusammenstöße gibt.", true, false, true)}} + {{ components.textbox("Woher weiß die Vision dass da ein Ball ist?", + "Sie hat es durch maschinelles Lernen gelernt. Doch wie funktioniert das? Ein Mensch lernt z.B. von seinen Eltern, + was ein Ball ist. Zuerst zeigt ein Elternteil auf einen Ball und sagt: Das ist ein Ball. Später zeigt das Kind selbst auf Gegenstände, + die wie ein Ball aussehen, und der Erwachsene bestätigt die Annahme oder berichtigt. Beim maschinellen Lernen funktioniert es ähnlich. + Während des Lernens versucht ein künstliches neuronales Netz immer wieder zu raten, ob und wo auf einem Bild ein Ball ist. + Das wird dann abgeglichen mit einem vorher von Menschen annotierten Bild, auf dem der Ball an der richtigen Stelle markiert wurde. + Das Netz ändert daraufhin die Gewichte seiner Neuronen und wird dadurch über die Zeit besser, bis es gut genug ist und das Training beendet wird. + Das fertig gelernte Netz wird dann noch mit neuen Bildern getestet und schließlich verbaut. Ab diesem Punkt wird nicht weiter gelernt, + sondern nur bereits Gelerntes auf neue Bilder angewendet.", false, false, false)}} +
+{% endblock %} + +{% block icons %} +{{ icon_components.icons("vision") }} +{% endblock %} + diff --git a/sync_includes_wolfgang_nuc.yaml b/sync_includes_wolfgang_nuc.yaml index d4ec2808f..9ed199c92 100644 --- a/sync_includes_wolfgang_nuc.yaml +++ b/sync_includes_wolfgang_nuc.yaml @@ -10,6 +10,7 @@ include: - bitbots_bringup - bitbots_diagnostic - bitbots_docs + - bitbots_education - bitbots_extrinsic_calibration - bitbots_ipm - bitbots_parameter_blackboard