Incom ist die Kommunikations-Plattform der Fachhochschule Potsdam

In seiner Funktionalität auf die Lehre in gestalterischen Studiengängen zugeschnitten... Schnittstelle für die moderne Lehre

Incom ist die Kommunikations-Plattform der Fachhochschule Potsdam mehr erfahren

3D Manipulator

Eine alternative Lösung für ein Eingabegerät für VR-Brillen

Idee

Meine Idee war es, ein Eingabegerät mithilfe von Arduino und Processing zu entwickeln, bei dem die Das Eingabemedium in verschiedenen Stadien unterschiedliche Funktionen einnimmt.

Prozess

Hierfür wollte ich das Arduino-Board Light Blue Bean einsetzen, das es extrem klein ist, kabellose Kommunikation per Bluetooth unterstützt und über ein Accelerometer verfügt.

So entstand schnell die Idee, ein Eingabe gerät zu entwickeln, das ein Potentiometer enthält. Dieses soll, je nach Lage des Accelerometers einen anderen Parameter manipulieren.

Um das Eingabegerät kompakt und leicht nutzbar zu machen, habe ich mich dazu entschlossen, ein Gehäuse dafür mit einem 3D-Drucker zu drucken. Zur Befestigung habe ich Gummizüge gewählt, damit das Das Objekt anpassbar an unterschiedliche Hände bleibt und schnell an- und abgelegt werden kann.

prozess-bild.pngprozess-bild.png

Funktionserklärung (Transkript zum Video)

Der 3D-Manipulator ist ein alternatives Eingabegerät für VR-Brillen.

Es besteht aus zwei Teilen: Dem Body, in dem sich der Mikrocontroller befindet und der Drehknopf mit dem verschiedene Werte manipuliert werden können. Der Body wird mithilfe von Gummibändern an der Handfläche befestigt, da dieser die Richtung der Hand im Raum erkennt. Der Drehknopf wird am Mittelfinger befestigt, so dass er sich gut mit Daumen und Zeigefinger drehen lässt.

In der VR-Brille sieht man nun das Objekt, in diesem Fall ein graues Quadrat.

Dreht man nun am Regler, während die Handfläche zu Seite zeigt, bewegt sich das Quadrat nach links oder nach rechts. Die rote LED zeigt an, ob die Hand richtig positioniert ist. Dreht man nun die Hand, so dass die Handfläche nach unten zeigt, so steuert man die Höhe des Quadrats. Zeigt die Handfläche nach vorn, entfernt sich das Quadrat oder kommt näher. Hält man die Hand in einer anderen Position, so erlöscht die LED und die Eingabe wird nicht weiterverarbeitet.

Arduino-Code

Weil ich eine Kommunikation zwischen dem Arduino-Board und dem Computer, der die VR-Brille bespielt, benötigte, habe ich zwei Code-Teile geschrieben.

Der eine Teil läuft lokal auf dem Arduino und sendet die drei Werte des Accelerometers und den einen Wert des Potentiometers, jeweils mit einem vorangestellten Buchstaben, damit der Computer die verschiedenen Werte zuordnen kann.

int poti = A1;

void setup() {
  Serial.begin();   
}

void loop() {
  AccelerationReading acceleration = Bean.getAcceleration();

  Serial.print('x');
  Serial.println(acceleration.xAxis);

  Serial.print('y');
  Serial.println(acceleration.yAxis);

  Serial.print('z');
  Serial.println(acceleration.zAxis);

  int potival = analogRead(poti); // read the poti
  Serial.print('p');
  Serial.println(potival);
}

Das Problem hierbei war, das ist so unglaublich viel Traffic an der über Bluetooth laufenden Schnittstelle verursacht habe, dass zum einen eine spürbar große Verzögerung entstand und die CPU-Auslastung meines empfangenden Processing-Programms innerhalb von wenigen Sekunden bei 140% lag. Deshalb habe ich den Code insofern verändert, dass nur noch Werte gesendet werden, wenn sich etwas ändert. Dies löste beide Probleme sofort.

int poti = A1;

int valx = 0;
int valy = 0;
int valz = 0;

int tempx = 0;
int tempy = 0;
int tempz = 0;
int tempp = 0;

void setup() {
  Serial.begin();
}

void loop() {
  AccelerationReading acceleration = Bean.getAcceleration();

  valx = map(acceleration.xAxis, -512, 511, 1, 8);
  if (tempx != valx) {
    tempx = valx;
    Serial.print('x');
    Serial.println(tempx);
  }

  valy = map(acceleration.yAxis, -512, 511, 1, 8);
  if (tempy != valy) {
    tempy = valy;
    Serial.print('y');
    Serial.println(tempy);
  }

  valz = map(acceleration.zAxis, -512, 511, 1, 8);
  if (tempz != valz) {
    tempz = valz;
    Serial.print('z');
    Serial.println(tempz);
  }

  if (tempx % 2 == 0 && tempy % 2 == 0 && tempz % 2 == 0) {
    Bean.setLed(255, 0, 0);
  } else {
    Bean.setLed(0, 0, 0);
  }

  int valp = analogRead(poti); // read the poti
  if (tempp != valp) {
    tempp = valp;
    Serial.print('p');
    Serial.println(valp); 
  }
}

Processing-Code

Für den Proof-of-concept habe ich mich dazu entschieden, die Darstellung auf ein Quadrat zu beschränken.

Die hiermit erzeugte Grafik habe ich per screen-mirroroing von meinem Computer auf mein iPhone gestreamt, das in der VR-Brille steckte.

Damit das Bild auf dreidimensional wahrgenommen wird, habe ich das Quadrat dupliziert und alle Parameter-Veränderungen auch auf das zweite, versetzte Quadrat übertragen.

Schwierig war an diesem Code, die zuvor mit Buchstaben-Indikatoren versehenen strings, die über Bluetooth und die serielle Schnittstelle ankamen, wieder aufzuschlüsseln und weiter zu verwerten.

import processing.serial.*; // import the lib

Serial port;

void setup() {
  size(1440, 900);
  noStroke();
  fill(102);

  String portname = Serial.list()[3]; // <-- this index may vary!
  port = new Serial(this, portname, 9600); // new serial port item
  port.bufferUntil('\n');
}

int vertical   = 81;
int horizontal = 81;
int depth = 0;
int size = 200;

float x = 0;
float y = 0;
float z = 0;
float p = 0;
float difp = 0;

void draw() {
  background(0, 200);
  //fill(255,0,0);
  rect(horizontal - depth, vertical, size, size);
  rect(horizontal + depth + 720, vertical, size, size);
}

void serialEvent (Serial myPort) {
  // get the ASCII string:
  String inString = myPort.readString();
  if (inString != null) {
    String indicator = inString.substring(0, 1);

    String val = inString.substring(1, inString.length()-1);
    println(val);

    ///// get x /////
    if (indicator.equals("x")== true) {
      x = float(val);
    }

    ///// get y /////
    if (indicator.equals("y")== true) {
      y = float(val);
    }

    ///// get z /////
    if (indicator.equals("z")== true) {
      z = float(val);
    }

    if (indicator.equals("p")== true) {
      difp = float(val) - p;
      p = float(val);
      //println(p);

      ///// Hand offen nach unten innen ///// Größe ändern /////
      if (x == 2 && y == 4 && z == 4) {
        println(size);
        size       += difp;

        if (size > 5 && size < 400) {
          horizontal -= difp/2;
          vertical   -= difp/2;
        }
        if (size < 5) {
          size = 5;
        }
        if (size > 300) {
          size = 300;
        }
      }

      ///// Hand offen nach unten ///// vertikal verschieben /////
      if (x == 4 && y == 4 && z == 2) {
        //println(vertical);
        vertical += difp;

        if (vertical < 5) {
          vertical = 5;
        }
        if (vertical > 720) {
          vertical = 720;
        }
      }

      ///// Hand offen nach links ///// horizontal verschieben /////
      if (x == 6 && y == 4 && z == 4) {
        //println(horizontal);
        horizontal += difp;

        if (horizontal < 5) {
          horizontal = 5;
        }
        if (horizontal > 540) {
          horizontal = 540;
        }
      }
      ///// Hand offen nach vorne ///// tiefenverschieben /////
      if (x == 4 && y == 2 && z == 4) {
        println(depth);
        depth += difp;
        size -= difp/2;

        if (size < 0) {
          depth -= difp;
          size += difp/2;
        }
        if (size > 300) {
          depth += difp;
          size -= difp/2;
        }
      }
    }
  }
}

Ein Projekt von

Fachgruppe

Werkstattpraxis

Art des Projekts

Studienarbeit im ersten Studienabschnitt

Betreuung

foto: Fabian Morón Zirfas

Zugehöriger Workspace

(Zinc Condor) Interface Werkstatt Physical Computing

Entstehungszeitraum

Sommersemester 2016