September 12, 2026

Communication interface for a robot


In contrast to a common assumption AI isn't located inside a robot but its an interface between the robot and its environment. the screenshot shows such an interface for a language game "simon says". The human formulates commands which are translated into word grid and then into a neural encoding. This translation ensures, that the robot understands the command and is able to execute it.

Let us go into the details.
command in natural language: "Simon says kick right leg"
word grid activation: [simon says], [kick], [leg], [right]
binary vector: [1,0,0,0,0,1,0,0,0,0,0,1,0,0,0,1]

The binary vector doesn't make sense for a human but its the prefered representation for a computer. It projects the communication into a numerical vector which is a list of numbers. These numbers can be stored, and converted into a movement of a robot.

September 10, 2026

Das frühe Archiv der Systemtheorie: Genese, Mechanik und thematisches Profil des Zettelkastens I von Niklas Luhmann (1952–1960)

1. Einleitung: Entstehungskontext und biografische Verortung (1952–1960)

Die 1950er-Jahre markieren in der intellektuellen Biografie Niklas Luhmanns eine Phase der Latenz und der autodidaktischen Fundierung, die für sein späteres soziologisches Œuvre von konstitutiver Bedeutung sein sollte. In den Jahren zwischen 1952 und 1960 war Luhmann weder als Soziologe noch als universitärer Wissenschaftler tätig. Nach seinem Jura-Studium in Freiburg arbeitete er zunächst als Referendar, später als Assistent am Oberverwaltungsgericht Lüneburg und ab 1955 als Verwaltungsbeamter im Kultusministerium des Landes Niedersachsen. Doch parallel zu dieser pragmatisch-juristischen Berufspraxis entfaltete Luhmann im privaten Arbeitszimmer ein außergewöhnliches Lektüre- und Forschungspensum. Es umfasste weite Teile der Philosophie, der Rechtswissenschaft, der frühen Organisations- und Verwaltungstheorie sowie zunehmend der US-amerikanischen Soziologie.

Aus dieser intensiven, fachübergreifenden Rezeption erwuchs ein tiefgreifendes Problem der Wissensorganisation. Luhmann erkannte früh die Defizite traditioneller Exzerpiermethoden. Wer in gebundenen Heften notiert oder Zettel starr alphabetisch nach Autoren oder starren Sachkategorien ablegt, bindet das Wissen an den Zufall der Lektürechronologie oder zwingt es in ein unflexibles taxonomisches Korsett, das neue interdisziplinäre Querverbindungen erstickt. Vor diesem Hintergrund vollzog Luhmann 1952 einen radikalen methodischen Bruch: Er begann mit dem Aufbau eines modularen, auf Zetteln basierenden Speichersystems, das heute in der Forschung als „Zettelkasten I“ (ZK I) firmiert.

Das Initialjahr 1952 markiert somit nicht nur den Beginn einer privaten Sammlung, sondern die Geburt einer spezifischen epistemologischen Praxis. Der Zettelkasten I, der in seiner aktiven Phase bis etwa 1960/1961 wuchs – bevor Luhmann nach seinem Studienaufenthalt in Harvard bei Talcott Parsons in die akademische Soziologie übertrat und mit dem „Zettelkasten II“ einen inhaltlichen und systematischen Neustart wagte –, umfasst rund 24.000 Zettel in 108 thematischen Abteilungen. Er ist das historische Dokument eines Geistes, der aus den Fesseln der juristischen Dogmatik ausbrach und durch die Mechanisierung seiner eigenen Lesefrucht die abstrakte Beobachtung von Gesellschaft einübte. In dieser formativen Phase diente das System Luhmann als Vehikel, um die immense Komplexität seiner Leseerfahrungen nicht nur zu bändigen, sondern produktiv zu wenden.

2. Architektonik und Mechanik des Zettelkastens I

Die historische Faszination des Zettelkastens I liegt weniger in seiner physischen Materialität als vielmehr in seiner logischen Architektonik. Physisch bestand das System aus standardisierten Papierkarten im Oktavformat (DIN A6), die in simplen Holzschubladen gelagert wurden. Die intellektuelle Innovation Luhmanns lag in der Abkehr von jedweder feststehenden, hierarchischen Systematik – etwa einer Klassifikation nach dem Vorbild der Dewey-Dezimalklassifikation. Stattdessen implementierte er eine dynamische, rein relationale Stellordnung.

Das Kernstück dieser Mechanik war das Prinzip der internen Verzweigung mittels eines alphanumerischen Codes. Jeder Zettel erhielt eine feste Nummer (z. B. 1, 2, 3), die ihn an einem festen physischen Ort im Kasten verankerte. Wenn Luhmann nun einen Gedanken zu Zettel 1 ergänzen wollte, der gedanklich nicht in das lineare Fortschreiten zu Zettel 2 passte, fügte er einen neuen Zettel direkt dahinter ein und bezifferte ihn mit 1a. Weitere Differenzierungen setzten diesen Rhythmus fort: Auf 1a folgte 1b, eine gedankliche Abzweigung aus 1a wurde zu 1a1, gefolgt von 1a2, und eine weitere Ausdifferenzierung von 1a1 wurde als 1a1a verschlagwortet.
Diese Technik löste ein massives physikalisches Problem: Sie erlaubte das unendliche interne Wachstum an jeder beliebigen Stelle des Kastens. Keine Vorentscheidung über die Wichtigkeit eines Themas musste getroffen werden; das System konnte organisch wuchern, ohne die vorhandene Ordnung zu zerstören.

Die Stellordnung allein hätte jedoch lediglich zu isolierten Gedankengängen geführt. Die eigentliche Emergenz – das oft von Luhmann selbst beschriebene Moment, in dem der Zettelkasten als "Kommunikationspartner" Überraschungen produziert – wurde durch das radikale Prinzip der Verweisung (Querverweise) generiert. Luhmann notierte auf den Karten Verweise zu Zetteln in völlig anderen Abteilungen des Kastens. Ein juristischer Gedanke in Abteilung 12 konnte so kurzgeschlossen werden mit einer erkenntnistheoretischen Reflexion in Abteilung 57. Diese Verweisungsnetzwerke emanzipierten die inhaltliche Struktur des Zettelkastens von seiner physischen Linearität. Der ZK I funktionierte de facto als analoger Hypertext.

Um in diesem dichten, nicht-hierarchischen Netzwerk Orientierung zu finden, verzichtete Luhmann auf Inhaltsverzeichnisse. Als einzige Zugangsmedien dienten ein separates Schlagwortregister sowie ein bibliografisches Register (der Literaturkasten). Im Schlagwortregister wurde ein Begriff (z. B. "Staat" oder "Organisation") mit nur ein bis drei zentralen Zettelnummern versehen (den sogenannten Einsprungstellen). Von diesen Startpunkten aus folgte Luhmann den netzartigen Verweisen auf den Karten selbst, um sich durch das Themengebiet zu navigieren.

Eine unabdingbare methodische Prämisse für das Gelingen dieses Systems war Luhmanns Selektionsregel: Der Zettelkasten nahm keine reinen Buchzusammenfassungen oder simplen Zitate auf. Luhmann exzerpierte nicht den Gedankengang eines Autors, sondern übersetzte die Lektüre unmittelbar in seine eigene Begriffssprache und in die Struktur des Kastens. Er extrahierte Theoreme, Begriffe und Relationen aus der Literatur und rekombinierte sie mit bereits bestehenden Zetteln. Der ZK I war somit von Beginn an kein passives Archiv fremden Wissens, sondern eine Maschine zur aktiven Theorieproduktion.

3. Subject-Mapping: Inhaltliche Schwerpunkte und Wissensbestände der Frühphase

Während die universitäre Wahrnehmung Luhmanns primär auf seiner ab den lateinischen 1960er-Jahren entwickelten, umfassenden Soziologie der Gesellschaft basiert, offenbart die inhaltliche Kartierung des Zettelkastens I (ZK I) ein gänzlich anderes Profil. Der ZK I ist das Protokoll einer geistigen Metamorphose – der schrittweisen Transformation eines juristisch-verwaltungswissenschaftlich geschulten Beamten in einen interdisziplinären Sozialtheoretiker.

Den dominanten Kern der Bestände im Zeitraum zwischen 1952 und 1960 bilden Themenfelder des öffentlichen Rechts, der Staats- und Verwaltungslehre sowie der Politikwissenschaft. Die frühesten Abteilungen des ZK I kreisen um klassische dogmatische Fragen:

    die Funktion von Grundrechten und Staatszielbestimmungen,

    die Grenzen des Verwaltungsermessens und

    das Wesen der Bürokratie im modernen Sozialstaat.

Luhmann beließ es jedoch nicht bei der juristischen Rekonstruktion von Normen. Sehr früh begann er, die Rechtswissenschaft phänomenologisch und funktionell aufzubrechen. Über die Rezeption der US-amerikanischen Verwaltungswissenschaft – allen voran den Arbeiten von Herbert A. Simon (Administrative Behavior) sowie Chester I. Barnard – hielten organisationstheoretische Kategorien Einzug in den Kasten. Die Frage, wie Entscheidungen unter den Bedingungen unvollständiger Information strukturiert werden und wie formale und informale Strukturen in Organisationen ineinandergreifen, entwickelte sich zu einem zentralen Motiv der Zettelreihen der späten 1950er-Jahre.

Zugleich zeigt der ZK I eine intensive Auseinandersetzung mit der Soziologie, noch bevor Luhmann 1960/61 nach Harvard ging, um bei Talcott Parsons zu studieren. Bereits in den Fünfzigerjahren exzerpierte Luhmann parsonssche Schriften sowie Werke der französischen Soziologie (u. a. Émile Durkheim, Marcel Mauss) und der philosophischen Anthropologie (u. a. Arnold Gehlen).

In dieser Rezeptionsphase zeichneten sich die begrifflichen Keimzellen der späteren Systemtheorie ab. Luhmann begann, fundamentale kognitive Werkzeuge einzuüben:

    Zweck-Mittel-Relationen: Die Umstellung vom substanziellen Denken auf funktionale Analysen, bei denen nicht mehr nach dem „Wesen“ eines Phänomens gefragt wird, sondern nach dessen Funktion für die Problemlösung.

    Struktur und Funktion: Das systematische Durchdenken von Systemen als Gefüge, die durch Strukturbildung Komplexität reduzieren.

    Formalität vs. Informalität: Die Beobachtung, dass Organisationen ihre Existenz der ständigen Spannung zwischen offiziellen Regelwerken und inoffiziellen Verhaltensweisen verdanken.

Der ZK I dokumentiert somit keine fertige Theorie, sondern den mühsamen, hochgradig kreativen Entstehungsprozess eines eigenen begrifflichen Instrumentariums. Er ist das Laboratorium, in dem der Jurist Luhmann das theoretische Rüstzeug schmiedete, das ihm in den 1960er-Jahren die schlagartige Integration in den soziologischen Fachdiskurs ermöglichte.

4. Epistemologischer Ertrag und Methodische Synthese

Der erkenntnistheoretische Ertrag des Zettelkastens I liegt weit über seinem bloßen Wert als Informationsspeicher. Aus wissenshistorischer Perspektive bildete die Symbiose aus Luhmann und seinem Kasten ein hybrides Kognitionssystem. Luhmann selbst sprach rückblickend von einer „Verdopplung der Persönlichkeit“ oder dem Zettelkasten als einem „Zweitgedächtnis“.

Die theoretische Tragweite dieser Konstellation lässt sich in drei Dimensionen verdichten:

    Emergenz durch Dezentralisierung: Durch den Verzicht auf eine übergeordnete Systematik besaß der ZK I kein Zentrum. Wissen war dezentral abgelegt. Wenn Luhmann über Jahre hinweg Zettel an disparate Stellen einsortierte und über die Registratur verknüpfte, erzeugte das System eine Eigendynamik. Bei Recherchen stieß er regelmäßig auf Verbindungen, die er Jahre zuvor notiert, aber längst vergessen hatte. Der ZK I wurde zu einer Suchmaschine für Analogien und strukturelle Isomorphien zwischen scheinbar unzusammenhängenden Sachverhalten.

    Abgrenzung von ZK I zu ZK II: Der Bruch um 1960/61 – markiert durch den Übergang zum Zettelkasten II – war die logische Konsequenz aus dem Wachstum des ersten Systems. Der ZK I war in seiner Struktur (108 oft noch sachlich gebundene Abteilungen) zwar hochflexibel, aber in Teilen noch von den juristisch-verwaltungswissenschaftlichen Ausgangsfragestellungen geprägt. Nach der intensiven Parsons-Lektüre in Harvard wählte Luhmann für den ZK II (ab 1961) eine noch abstraktere, rein funktionale Systematik, die ihn fortan durch das gesamte soziologische Hauptwerk trug. Der ZK I blieb dennoch das Fundament, auf dem Luhmanns frühe Monografien – wie Funktionen und Folgen formaler Organisation (1964) oder Grundrechte als Institution (1965) – direkt aufbauten.

    Materialität als Denkvoraussetzung: Luhmanns Theoriearbeit war nicht das Produkt rein abstrakter Geistestätigkeit im luftleeren Raum, sondern das Ergebnis einer haptischen, mediengebundenen Praxis. Ohne die Disziplin des täglichen Zettelschreibens, Bezifferns und Verweisens wäre die gigantische Syntheseleistung der Luhmannschen Systemtheorie schlicht nicht denkbar gewesen.

Fazit:

Der Zettelkasten I im Zeitraum von 1952 bis 1960 ist weit mehr als eine kurios-analoge Datenbank eines Arbeitsbesessenen. Er steht exemplarisch für die Entstehung moderner Theoriearchitektur im Medium der Karteikarte. In der Isolation des Verwaltungsdienstes schuf Niklas Luhmann mit dem ZK I eine Denkmaschine, die es ihm erlaubte, die Komplexität der modernen Gesellschaft nicht nur zu archivieren, sondern sie in ihrer eigenen netzartigen Struktur spiegelbildlich nachzubilden.

Müllsuch-Roboter mit neural encoding

In einer 2d Karte ist ein Roboter mit einem vision cone unterwegs, der Müllobjekte kartieren soll. Es gibt einen manuellen Modus wo der User den Roboter mittels Pfeiltasten steuert und einen KI Modus der mit [k] aktiviert wird.

Der Roboter gibt die Statusinformationen einmal als Textnachrichten auf dem Bildschirm aus und zusätzlich noch als neural encoding, dieser ist ein feature vector mit 10 numerischen Werten. Im KI Modus wird dieser Feature vector verwendet um die Aktionen des Roboter zu planen.

 import sys
import math
import random
import numpy as np
import pygame

# --- KONFIGURATION & FARBEN ---
GRID_WIDTH = 30
GRID_HEIGHT = 20
CELL_SIZE = 30

GRID_PIXEL_W = GRID_WIDTH * CELL_SIZE
GRID_PIXEL_H = GRID_HEIGHT * CELL_SIZE
UI_HEIGHT = 180
WINDOW_WIDTH = GRID_PIXEL_W
WINDOW_HEIGHT = GRID_PIXEL_H + UI_HEIGHT

# Farben (RGB)
COLOR_BG = (30, 30, 35)
COLOR_WALL = (50, 50, 60)
COLOR_TRASH = (210, 45, 45)
COLOR_UNKNOWN = (100, 100, 110)
COLOR_MAPPED_FREE = (240, 240, 245)
COLOR_MAPPED_TRASH = (255, 140, 0)
COLOR_ROBOT = (30, 144, 255)
COLOR_VISION = (255, 255, 0, 60)

# Neue UI-Farben (Weißer Hintergrund, schwarzer Text)
COLOR_UI_BG = (255, 255, 255)
COLOR_UI_TEXT = (0, 0, 0)

# Zell-Typen
EMPTY = 0
WALL = 1
TRASH = 2


class Robot:

    def __init__(self, x, y, grid_w, grid_h):
        self.x = x
        self.y = y
        self.grid_w = grid_w
        self.grid_h = grid_h
        self.orientation = 0  # 0=Rechts, 90=Unten, 180=Links, 270=Oben
        self.fov_angle = 90
        self.fov_range = 5

    def move(self, dx, dy, grid):
        new_x = self.x + dx
        new_y = self.y + dy

        if dx == 1:
            self.orientation = 0
        elif dx == -1:
            self.orientation = 180
        elif dy == 1:
            self.orientation = 90
        elif dy == -1:
            self.orientation = 270

        if (
            0 <= new_x < self.grid_w
            and 0 <= new_y < self.grid_h
            and grid[new_y][new_x] != WALL
        ):
            self.x = new_x
            self.y = new_y
            return True
        return False


class Environment:

    def __init__(self, w, h):
        self.w = w
        self.h = h
        self.grid = np.zeros((h, w), dtype=int)
        self.generate_map()

    def generate_map(self):
        self.grid[0, :] = WALL
        self.grid[-1, :] = WALL
        self.grid[:, 0] = WALL
        self.grid[:, -1] = WALL

        self.grid[4:14, 8] = WALL
        self.grid[6, 8:18] = WALL
        self.grid[12:18, 20] = WALL

        trash_positions = [
            (3, 3),
            (5, 12),
            (10, 15),
            (15, 4),
            (22, 8),
            (25, 15),
            (12, 2),
            (18, 16),
        ]
        for tx, ty in trash_positions:
            self.grid[ty, tx] = TRASH


class RobotSystem:

    def __init__(self):
        pygame.init()
        pygame.display.set_caption(
            "2D Robot Mapping & Neural Encoding Simulation"
        )
        self.screen = pygame.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT))
        self.clock = pygame.time.Clock()
        self.font = pygame.font.SysFont("Arial", 16, bold=False)

        self.env = Environment(GRID_WIDTH, GRID_HEIGHT)
        self.robot = Robot(2, 2, GRID_WIDTH, GRID_HEIGHT)

        self.robot_map = np.full((GRID_HEIGHT, GRID_WIDTH), -1, dtype=int)
        self.status_message = "SYS_INIT: ROBOT ONLINE."
        self.feature_vector = np.zeros(10)

        # KI Steuerung
        self.ai_mode = False
        self.ai_move_timer = 0

    def compute_vision_and_map(self):
        visible_cells = set()
        trash_in_fov = []

        start_angle = self.robot.orientation - (self.robot.fov_angle / 2)
        end_angle = self.robot.orientation + (self.robot.fov_angle / 2)

        for angle_deg in np.linspace(start_angle, end_angle, num=30):
            rad = math.radians(angle_deg)
            dx = math.cos(rad)
            dy = math.sin(rad)

            for step in range(1, self.robot.fov_range + 1):
                cx = int(round(self.robot.x + dx * step))
                cy = int(round(self.robot.y + dy * step))

                if 0 <= cx < GRID_WIDTH and 0 <= cy < GRID_HEIGHT:
                    visible_cells.add((cx, cy))
                    cell_val = self.env.grid[cy][cx]
                    self.robot_map[cy][cx] = cell_val

                    if cell_val == TRASH:
                        dist = math.hypot(cx - self.robot.x, cy - self.robot.y)
                        trash_in_fov.append((cx, cy, dist))

                    if cell_val == WALL:
                        break
                else:
                    break

        self.robot_map[self.robot.y][self.robot.x] = EMPTY
        visible_cells.add((self.robot.x, self.robot.y))
        return visible_cells, trash_in_fov

    def update_neural_encoding(self, trash_in_fov):
        """Erzeugt den 10-dimensionalen semantischen Feature-Vektor."""
        v = np.zeros(10)

        # v0, v1: Position (normiert)
        v[0] = round(self.robot.x / (GRID_WIDTH - 1), 2)
        v[1] = round(self.robot.y / (GRID_HEIGHT - 1), 2)

        # v2-v5: Hindernis-Nähe (Vorne, Rechts, Hinten, Links) -> 1.0 = Wand nah
        dirs = [
            self.robot.orientation,
            (self.robot.orientation + 90) % 360,
            (self.robot.orientation + 180) % 360,
            (self.robot.orientation + 270) % 360,
        ]

        for i, d in enumerate(dirs):
            rad = math.radians(d)
            dx, dy = int(round(math.cos(rad))), int(round(math.sin(rad)))
            dist = 0
            cx, cy = self.robot.x, self.robot.y
            while True:
                cx += dx
                cy += dy
                dist += 1
                if (
                    not (0 <= cx < GRID_WIDTH and 0 <= cy < GRID_HEIGHT)
                    or self.env.grid[cy][cx] == WALL
                ):
                    break
            v[2 + i] = round(1.0 / max(dist, 1), 2)

        # v6: Müll im Sichtfeld (0.0 oder 1.0)
        v[6] = 1.0 if len(trash_in_fov) > 0 else 0.0

        # v7: Distanz/Nähe zum Müll (1.0 = sehr nah, 0.0 = weit weg/keiner)
        if len(trash_in_fov) > 0:
            min_dist = min([t[2] for t in trash_in_fov])
            v[7] = round(max(0.0, 1.0 - (min_dist / self.robot.fov_range)), 2)
        else:
            v[7] = 0.0

        # v8: Kartierungsfortschritt
        mapped_count = np.sum(self.robot_map != -1)
        v[8] = round(mapped_count / (GRID_WIDTH * GRID_HEIGHT), 2)

        # v9: Müll-Dichte / Erfassungsquote
        found_trash = np.sum(self.robot_map == TRASH)
        v[9] = round(min(1.0, found_trash / max(1, mapped_count * 0.1)), 2)

        self.feature_vector = v

    def ai_decide_move(self):
        """KI-Entscheidung: Greift AUSSCHLIESSLICH auf den Feature-Vektor zu."""
        vec = self.feature_vector

        # Mögliche Bewegungsrichtungen: [(dx, dy), Orientierung]
        moves = [
            ((1, 0), 0),  # Rechts
            ((0, 1), 90),  # Unten
            ((-1, 0), 180),  # Links
            ((0, -1), 270),  # Oben
        ]

        valid_moves = []
        for (dx, dy), orient in moves:
            # Zuordnung der Vektor-Wände (v2..v5) zur relativen Ausrichtung
            rel_angle = (orient - self.robot.orientation) % 360
            idx = int(rel_angle // 90) + 2

            # Wenn die Wand nicht direkt davor steht (v < 1.0 ist frei)
            if vec[idx] < 1.0:
                valid_moves.append(((dx, dy), orient, vec[idx]))

        if not valid_moves:
            return

        # STRATEGIE 1: Müll jagen (wenn v6 == 1.0)
        if vec[6] == 1.0:
            best_move = None
            best_score = -999

            for (dx, dy), orient, wall_proximity in valid_moves:
                # Teste virtuell, wie sich v7 verändern würde
                # Ausrichtungsauswertung in Richtung Müll
                score = -wall_proximity * 2.0
                if orient == self.robot.orientation:
                    score += 2.0  # Bevorzuge Vorwärtsbewegung zum Müll

                if score > best_score:
                    best_score = score
                    best_move = (dx, dy)

            if best_move:
                self.robot.move(best_move[0], best_move[1], self.env.grid)
                return

        # STRATEGIE 2: Karte erkunden (Wänden ausweichen, geradeaus bevorzugen)
        best_move = None
        best_score = -999

        for (dx, dy), orient, wall_proximity in valid_moves:
            # Score: Viel Platz (geringer Wall-Proximity Wert) + Kontinuität
            score = (1.0 - wall_proximity) * 3.0
            if orient == self.robot.orientation:
                score += 1.5  # Vorwärtsdrang
            score += random.uniform(0.0, 0.5)  # Zufallskomponente gegen Schleifen

            if score > best_score:
                best_score = score
                best_move = (dx, dy)

        if best_move:
            self.robot.move(best_move[0], best_move[1], self.env.grid)

    def update_telemetry(self, trash_in_fov):
        mode_str = "AI-MODE (AUTONOMOUS)" if self.ai_mode else "MANUAL (KEYBOARD)"
        msg_parts = [f"MODE: {mode_str}", f"POS:[{self.robot.x},{self.robot.y}]"]

        if trash_in_fov:
            closest = min(trash_in_fov, key=lambda item: item[2])
            msg_parts.append(
                f"ALERT: TRASH DETECTED AT [{closest[0]},{closest[1]}]"
            )
        else:
            msg_parts.append("SCANNING... NO TRASH IN FOV")

        total_trash_mapped = np.sum(self.robot_map == TRASH)
        msg_parts.append(f"MAPPED TRASH TOTAL: {total_trash_mapped}")

        self.status_message = " | ".join(msg_parts)

    def draw(self, visible_cells):
        self.screen.fill(COLOR_BG)

        # 1. Gitter & Map zeichnen
        for y in range(GRID_HEIGHT):
            for x in range(GRID_WIDTH):
                rect = pygame.Rect(
                    x * CELL_SIZE, y * CELL_SIZE, CELL_SIZE, CELL_SIZE
                )
                mapped_val = self.robot_map[y][x]
                real_val = self.env.grid[y][x]

                if mapped_val == -1:
                    color = COLOR_UNKNOWN
                elif mapped_val == WALL:
                    color = COLOR_WALL
                elif mapped_val == TRASH:
                    color = COLOR_MAPPED_TRASH
                else:
                    color = COLOR_MAPPED_FREE

                pygame.draw.rect(self.screen, color, rect)

                if (x, y) in visible_cells and real_val == TRASH:
                    pygame.draw.circle(
                        self.screen, COLOR_TRASH, rect.center, CELL_SIZE // 3
                    )

                pygame.draw.rect(self.screen, (50, 50, 50), rect, 1)

        # 2. Vision Cone
        rx_pix = self.robot.x * CELL_SIZE + CELL_SIZE // 2
        ry_pix = self.robot.y * CELL_SIZE + CELL_SIZE // 2

        cone_surface = pygame.Surface(
            (GRID_PIXEL_W, GRID_PIXEL_H), pygame.SRCALPHA
        )
        for cx, cy in visible_cells:
            c_rect = pygame.Rect(
                cx * CELL_SIZE, cy * CELL_SIZE, CELL_SIZE, CELL_SIZE
            )
            pygame.draw.rect(cone_surface, COLOR_VISION, c_rect)
        self.screen.blit(cone_surface, (0, 0))

        # 3. Roboter
        pygame.draw.circle(
            self.screen, COLOR_ROBOT, (rx_pix, ry_pix), CELL_SIZE // 2 - 2
        )
        rad = math.radians(self.robot.orientation)
        end_x = rx_pix + math.cos(rad) * (CELL_SIZE // 2)
        end_y = ry_pix + math.sin(rad) * (CELL_SIZE // 2)
        pygame.draw.line(
            self.screen, (255, 255, 255), (rx_pix, ry_pix), (end_x, end_y), 3
        )

        # 4. UI / Textfeld (WEISSER HINTERGRUND & SCHWARZER TEXT)
        ui_rect = pygame.Rect(0, GRID_PIXEL_H, WINDOW_WIDTH, UI_HEIGHT)
        pygame.draw.rect(self.screen, COLOR_UI_BG, ui_rect)
        pygame.draw.line(
            self.screen,
            (200, 200, 200),
            (0, GRID_PIXEL_H),
            (WINDOW_WIDTH, GRID_PIXEL_H),
            2,
        )

        # Statuszeile
        txt_surface = self.font.render(
            f"> STATUS: {self.status_message}", True, COLOR_UI_TEXT
        )
        self.screen.blit(txt_surface, (15, GRID_PIXEL_H + 15))

        # Neural Vector Zeile
        vec_title = self.font.render(
            "> NEURAL FEATURE VECTOR [v0..v9]:", True, COLOR_UI_TEXT
        )
        self.screen.blit(vec_title, (15, GRID_PIXEL_H + 45))

        vec_str = np.array2string(
            self.feature_vector, precision=2, suppress_small=True
        )
        vec_surface = self.font.render(
            f"  {vec_str}", True, COLOR_UI_TEXT
        )
        self.screen.blit(vec_surface, (15, GRID_PIXEL_H + 65))

        # Vektor-Legende
        legend = "[PosX, PosY, DistN, DistE, DistS, DistW, TrashVisible, TrashDist, MapProgress, TrashDensity]"
        leg_surface = self.font.render(f"  {legend}", True, COLOR_UI_TEXT)
        self.screen.blit(leg_surface, (15, GRID_PIXEL_H + 90))

        # Steuerungshinweis
        ctrl_str = "Steuerung: Pfeiltasten (Manuell) | Taste 'K' drücken (KI-Modus Umschalten)"
        ctrl_surface = self.font.render(ctrl_str, True, COLOR_UI_TEXT)
        self.screen.blit(ctrl_surface, (15, GRID_PIXEL_H + 130))

        pygame.display.flip()

    def run(self):
        running = True
        while running:
            self.clock.tick(30)
            self.ai_move_timer += 1

            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    running = False
                elif event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_k:
                        # KI-Modus umschalten
                        self.ai_mode = not self.ai_mode
                    elif not self.ai_mode:
                        # Manuelle Steuerung nur, wenn KI aus ist
                        if event.key == pygame.K_UP:
                            self.robot.move(0, -1, self.env.grid)
                        elif event.key == pygame.K_DOWN:
                            self.robot.move(0, 1, self.env.grid)
                        elif event.key == pygame.K_LEFT:
                            self.robot.move(-1, 0, self.env.grid)
                        elif event.key == pygame.K_RIGHT:
                            self.robot.move(1, 0, self.env.grid)

            # KI-Schritt ausführen (alle 5 Frames für eine flüssige Bewegung)
            if self.ai_mode and self.ai_move_timer >= 5:
                self.ai_decide_move()
                self.ai_move_timer = 0

            # Sensorik & System-Updates
            visible_cells, trash_in_fov = self.compute_vision_and_map()
            self.update_neural_encoding(trash_in_fov)
            self.update_telemetry(trash_in_fov)

            # Zeichnen
            self.draw(visible_cells)

        pygame.quit()
        sys.exit()


if __name__ == "__main__":
    sim = RobotSystem()
    sim.run()

September 09, 2026

KI und die Entdeckung der Systemumgebung

Über Jahrzehnte verharrte die Debatte um Künstliche Intelligenz in einem narzisstischen Zirkelschluss. Die zentrale Fragestellung lautet schlicht: Wie bringt man einer isolierten Maschine das Denken bei? Der Fokus der Informatik lag fast ausschließlich auf dem System selbst – auf eleganter Code-Architektur, der Kompilation in C/C++, optimierten Laufzeiten und internen Entscheidungsbäumen. Die Maschine war ein isoliertes Gehirn im Reagenzglas.

Der entscheidende Paradigmenwechsel vollzog sich um das Jahr 1990 mit dem Aufkommen der Nouvelle AI, maßgeblich geprägt durch Rodney Brooks. Sein Ansatz der Behavior-Based Robotics stürzte das klassische Dogma um: Intelligenz ist keine Eigenschaft des Quellcodes, sondern das Produkt von Interaktion mit der Umwelt.

Die Kernmechanismen dieser Wende:

- Vom geschlossenen zum offenen System: Ein autarker Rechner benötigt kein komplexes Umweltschnittstellensystem. Sobald jedoch die physische Realität ins Spiel kommt, rückt das Kommunikationsproblem in den Mittelpunkt.

- Auflösung klassischer Informatik-Konzepte: In einem rein reaktiven, offenen System verlieren 32-Bit-RISC-Architekturen, starre Expertensysteme oder abstrakte Suchalgorithmen an Primärbedeutung. An ihre Stelle treten Sensorik, Kommunikationsprotokolle und die Notwendigkeit, Signale in Echtzeit zu verarbeiten.

- Emergente statt programmierte Intelligenz: Wie schon bei den kybernetischen „Schildkröten“ von William Grey Walter in den 1950ern erzeugt die Umwelt das Verhalten. Fährt ein Roboter wandbegrenzend durch einen Korridor, speichert er keinen Raumplan; die Architektur des Raumes ist sein Gedächtnis.

Intelligenz entsteht somit erst am Interface. Nicht der Algorithmus bestimmt das Handeln, sondern das dynamische Zusammenspiel aus Sensorik, Rückkopplung und Umweltbedingungen.

September 08, 2026

State of the Art KI Technologien

 Der word2vec Algorithmus oder Teleoperation von Robotern klingen zunächst wie Quatsch. Letzteres hat Edwin Olsen im Jahr 2010 in einem Votrag erläutert und sein Publikum hat gelacht als er Roboter mit Hilfe eines Joysticks steuern wollte. Sein Vorschlag war das genaue Gegenteil von dem, woran die Informatik seit Jahren geforscht hatte, und passte nichts ins Bild eines autonomen Roboters.[1]

Ähnlich muss es Tomas Mikolov ergangen sein, als seinen word2vec Algorithmus einer breiten Öffentlichkeit vorstellte. Technisch gesehen ist die Umwandlung von Wörter in numerische Vektoren simpel, unklar bleibt lediglich was der Zweck davon ist.

Warum beide KI Forscher ab dem Jahr 2010 auf leicht sonderbare Theorien kamen war, dass frühere Versuche künstliche Intelligenz zu erzeugen, nicht funktionierte. Die Zielstellung autonome Roboter zu programmieren welche ohne Fernsteuerung funktionieren, wurde 50 Jahre lang erfolglos versucht, und das Ziel neuronale Netze mit numerischen Mustern zu trainieren wurde ebenfalls lange versucht ohne dass sich damit denkende Maschinen erzielen ließen. Folgerichtig wurden diese Versuche eingestellt zugunsten neuer unbekannter Verfahren.

Man kann sich die Atmosphäre im Jahr 2010 ungefähr so vorstellen. Der eine Robotik-Forscher behauptet, dass man Roboter mittels Joystick steuern soll, der nächste KI Forscher welcher auf Suchmaschinen spezialisiert ist schlägt vor, Worte als Vektoren in neuronalen Netzen zu speichern. Beide Ideen klingen für die damalige Community wie Unsinn. Sie verstehen zwar was es technisch bedeutet, aber sie sehen keinen rationalen Grund es zu tun.

[1] Winning the MAGIC 2010 Autonomous Robotics Competition https://www.youtube.com/watch?v=OuOQ--CyBwc

September 04, 2026

Neural encoding of grounded language

 _

The picture shows a random generator which produces geometric shapes. The output is shown in 3 formats: graphical, text and as neural encoding.

The numerical vector is: [size_code, color_code, shape_code, x_norm, y_norm, border_code, corner_code] 

September 03, 2026

Car racing with grounded language

 The screenshot shows a game AI prototype based on grounded language. The current game state is converted first into textual description which is then processed by the rule system to determine the next action. The textual log file at the bottom of the screen is the decision making logic.

The main advantage of grounded language is, that it compress the game state into a small amount of possible states. Instead of describing the racing game as a vision task which contains of a 2d pixel game, the perception system converts the game into a list of words which are "lane is safe, lane is clear, collision". This small amount of discrete states makes it easier to program a rule system which determines what the car is doing next in the game.

From a programming perspective its a mix of racing video game on top of the screen and text adventure at the bottom. Even it is possible to implement the game AI on outdated 8bit homecomputers from the 1980s, the software is very new because it assumes a certain understanding of Artificial intelligence. AI isn't described as algorithms but AI shown in the prototype is a textual description of the game state.

September 02, 2026

Prototypen für ein selbstfahrendes Auto

„Du bist tatsächlich gekommen“, sagte Dr. Lena Hoffmann und winkte ihm auf dem Parkplatz entgegen.

„Eine Einladung zu einer Probefahrt mit einem selbstfahrenden Auto lehnt man als Informatiker nicht ab“, antwortete Daniel Weber. Er blieb vor dem silbernen Wagen stehen und betrachtete die glatte Karosserie. Auf dem Dach saßen mehrere Kameras und flache Sensoren, die sich kaum sichtbar in das Design einfügten.

Lena öffnete die Beifahrertür. „Dann steig ein. Ich sitze heute hinter dem Steuer.“

Daniel hob überrascht die Augenbrauen. „Du fährst selbst?“

„Ich überwache das System. Das ist nicht dasselbe.“ Sie setzte sich auf den Fahrersitz und legte die Hände locker auf das Lenkrad. „Das Auto übernimmt die meisten Aufgaben. Ich kann aber jederzeit eingreifen.“

Daniel nahm neben ihr Platz. Im Innenraum gab es nur wenige Schalter. Ein breites Display erstreckte sich über das Armaturenbrett, doch zunächst blieb es dunkel.

„Wie viele Sensoren benutzt das Fahrzeug?“, fragte Daniel.

„Vierzehn Kameras, sechs Radar-Module und drei Lidar-Einheiten“, erklärte Lena. „Dazu kommen GPS, digitale Karten, Ultraschallsensoren und eine ständige Überwachung des Fahrzeugzustands. Die KI kombiniert alle Daten zu einem Modell der Umgebung.“

„Und wie entscheidet sie, was sie tun soll?“

„Nicht wie ein Mensch, der spontan denkt: Dort ist ein Fahrradfahrer, ich bremse. Das System verarbeitet viele Datenströme gleichzeitig. Es erkennt Objekte, berechnet deren Bewegungen und erstellt mehrere mögliche Zukunftsszenarien. Für jedes Szenario bewertet es Sicherheit, Verkehrsregeln, Komfort und die Wahrscheinlichkeit von Fehlern.“

Daniel schnallte sich an. „Das klingt nach ziemlich viel Verantwortung für ein System, das niemand direkt verstehen kann.“

Lena lächelte. „Genau deshalb habe ich die innere Stimme eingebaut.“

„Die innere Stimme?“

„Eine verständliche Darstellung der wichtigsten Wahrnehmungen und Entscheidungen. Keine geheimen Gedanken, sondern eine technische Übersetzung der Prozesse.“

Sie tippte auf das Display. Über der Windschutzscheibe leuchtete plötzlich eine transparente Anzeige auf. Auf dem Head-up-Display erschienen grüne Linien auf der Straße, kleine Markierungen um parkende Fahrzeuge und gelbe Umrisse um Fußgänger.

Darunter stand:

UMGEBUNG ERKANNT:
Fahrbahn frei.
Parkendes Fahrzeug, Entfernung 18 Meter.
Fußgänger am linken Gehweg, Bewegungsrichtung: parallel zur Fahrbahn.
Geschätzte Geschwindigkeit: 5 Kilometer pro Stunde.

Daniel beugte sich leicht nach vorn. „Das wird direkt auf die Scheibe projiziert?“

„Ja. Die Anzeige bleibt im Sichtfeld, ohne den Fahrer abzulenken. Du kannst die Informationen auch hören.“

Lena drückte eine Taste am Lenkrad. „Fahrzeug, beschreibe deine aktuelle Umgebung.“

Eine ruhige, geschlechtsneutrale Stimme antwortete aus den Lautsprechern:

„Ich erkenne eine zweispurige Zufahrt. Die zulässige Geschwindigkeit beträgt dreißig Kilometer pro Stunde. Ein Lieferwagen nähert sich von rechts. Abstand: vierundzwanzig Meter. Zwei Fußgänger befinden sich auf dem Gehweg. Keine Hindernisse auf der geplanten Fahrspur.“

Daniel sah Lena an. „Du kannst einfach mit dem Auto sprechen?“

„Ja. Das Sprachmodul ist nicht nur für Befehle gedacht. Es erlaubt mir, die Wahrnehmung des Systems abzufragen.“

„Fahrzeug, warum reduzierst du die Geschwindigkeit?“, fragte sie.

„Ein Kind steht neben einem geparkten Fahrzeug. Aufgrund der eingeschränkten Sicht besteht die Möglichkeit, dass es die Fahrbahn betritt. Ich reduziere die Geschwindigkeit auf fünfzehn Kilometer pro Stunde und verschiebe die geplante Fahrlinie nach links.“

Das Auto setzte sich langsam in Bewegung. Auf dem Head-up-Display wanderte eine blaue Linie über die Straße. Der Wagen folgte ihr mit sanften Lenkbewegungen.

Daniel verschränkte die Arme. „Du hast das alles programmiert?“

„Ich habe die Wahrnehmungs- und Erklärungsschicht entwickelt. Das Fahrverhalten selbst basiert auf mehreren neuronalen Netzen und regelbasierten Sicherheitsmodulen. Wichtig ist, dass die KI nicht nur erkennt, sondern ihre Unsicherheit mitteilt.“

„Kann sie das?“

„Frag sie.“

Daniel blickte auf die Straße. Ein Fahrradfahrer fuhr zwischen zwei parkenden Autos hervor.

„Fahrzeug, wie sicher bist du bei der Erkennung des Fahrradfahrers?“

„Erkennungssicherheit: siebenundneunzig Prozent. Bewegungsprognose: achtundsiebzig Prozent. Mögliche Abweichung nach links. Ich halte an.“

Das Auto bremste kontrolliert und blieb stehen. Der Fahrradfahrer überquerte die Einfahrt, ohne die beiden Insassen zu bemerken.

Daniel atmete aus. „Die Erklärung ist tatsächlich hilfreich. Sie sagt nicht einfach nur, was sie tut, sondern auch, wie sicher sie sich ist.“

„Das ist entscheidend“, sagte Lena. „Menschen müssen verstehen, wann sie dem System vertrauen können und wann nicht. Eine KI darf keine falsche Sicherheit erzeugen.“

„Und wenn du nicht eingreifen würdest?“

„Dann würde das Auto nach seinen Sicherheitsregeln handeln. Aber ich bleibe verantwortlich. Deshalb muss ich jederzeit aufmerksam sein.“

Auf dem Display erschien eine neue Meldung:

FAHRRADFAHRER PASSIERT.
Fahrbahn wieder frei.
Geplante Route wird fortgesetzt.

Lena sah Daniel kurz an. „Noch eine Frage?“

„Ja“, sagte er. „Kannst du ihr auch sagen, wohin sie fahren soll?“

„Natürlich.“ Sie lächelte und wandte sich an das Fahrzeug. „Bring uns zu dem Ort, an dem du zum ersten Mal selbstständig eine Entscheidung getroffen hast.“

Für einen Moment schwieg die KI.

Dann antwortete sie: „Zielangabe ist unklar. Meinst du das Testgelände?“

Daniel lachte. „Sie kann also doch nicht alles.“

„Noch nicht“, sagte Lena und gab leicht Gas. „Aber sie lernt, bessere Fragen zu stellen.“