Interactive Digital Tree by Harjot

Hello everyone! Great to see everybody’s final projects showcased during the final class. Definitely a successful finale for the class.

Approach

As mentioned in my proposal post I decided to formulate a thesis topic that suited my interests and what I hope to explore in greater detail within a two-year timeframe.

In my thesis work, I plan to explore the presence of self in a world where social networking and data mobilization have gained predominance. I look to employ technology, in the form of pre-existing computer applications and custom-made hardware configurations, to discover how individuals relate to one another and their environment both emotionally and psychologically. Additionally, I am interested in utilizing the human body as a natural interface, one which is already rich with information and sensory modes of communication, in various design projects.

Creating a moment of emotional contact between a user and nature was my specific concern and so I wanted to create natural ways to communicate with a digital object which would draw parallels with the ways in which one interacts physically with nature.

Original Mission Statement

I want to visualize an ethereal fantasy tree onto a large projection screen which grows and changes before users as a result of interaction. User behaviour is the key input in my concept and comes in the form of interaction with a custom-made peripheral device–something like a magical sphere. Ideally, the spherical object would be lit up from inside and use colour as well as (fingers-crossed) vibration to respond to user input. I am also considering using a webcam or (again fingers-crossed) the Kinect so that I may capture user movement to further influence the reaction behaviours of the tree. I have envisioned this scenario to take place in a dark environment where focus is initially given to the ‘magical sphere’ object, towards which a curious user walks and with which he/she hopefully decides to interact, leading to the rapid birth and growth of a beautifully intricate tree structure, taking influence from user input to guide its progressive growth. My motivation for this concept comes from my understanding that nature (the organic world) benefits the brain in ways that allow individuals to think and feel more clearly. Studies on children with ADD have found that increased exposure to nature, i.e. visiting a park before going to school, and taking occasional recess breaks, helped to calm the mind and so allowed students to perform in school better than usual, this trend was similar to that observed in control groups. Additionally, this is also the thinking behind the belief that patients recover more quickly when they can see trees from their windows. [Ref: “The Cognitive Benefits of Interacting With Nature” by Marc G. Berman, John Jonides, and Stephen Kaplan, “Recess in Elementary School: What Does the Research Say?” by Olga S. Jarrett, “Recess—It’s Indispensable!” by Olga S. Jarrett and Sandra Waite-Stupiansky]

Context & Concept

The portrayal of a tree which alters its behaviour in response to user engagement with an external object. I felt that creating a scene and placing the user in a visual context from the start was important in creating a strong narrative. This was accomplished by the use of background imagery which depicts a dark forest with almost dead-looking tree trunks. The addition of music, via the Minim audio library, helped heighten the sense of presence within context; a somber tune playing in the background and lasting for the entirety of the sketch conveys the isolation and out-of-touch associations made with limited human-to-nature interactions that exist today, as a result of rapid urban development. The ability to interact with nature via touch and speaking were modes of communication that I felt necessary to explore.

The Arduino Device

Now this is where I had some difficulties! Unfortunately, my XBee wireless kit did not arrive in time and so enclosing my peripheral hardware was really not a viable option and I was not able to come up with any last-minute fixes (excuses, I know…should have been better prepared!). The morning of I decided that wireless would still put my device over-the-edge so I went over to Creatron and made a not-so-wise investment in a BlueSmirf Silver Bluetooth Module (BTW: I had a very negative experience with the sales clerk at Creatron…he was being extremely rude and so we had a not-so-nice exchange of words). Although I managed to get to Bluetooth module up-and-running (after reading MANY how-to guides online) the thing was very moody and developed a life of its own…this was why I decided not to chance my presentation with entertaining the Bluetooth capability–being unsure if I would be able to have a successful showcasing of my project. Finally, the ‘wireless’ device was comprised of an Arduino and Breadboard, both of which were mounted on a compact tray, an Electret Microphone, push switch, and Force sensor. The three interactive devices were all connected to the Arduino as analog devices communicating via serial input. The BlueSmirf was connected to the RX and TX pins on the Arduino (reversed) and to the GND and 3.3V. I also invested in a 9V battery adapter for a complete wireless experience.

Serial Communication

The Visual Color Mixer example on the Arduino website helped me send data from multiple serial devices from the Arduino to Processing without interfering values when engaging with multiple input sensors simultaneously. The trick was basically to capture the string of data coming in from the serial ports and split each value for the respective input sensor with commas–designating parameters for value input in Processing.

Function & Interaction

  • Push Switch = Grow the tree from a simple root into a more complex structure. Unique random generation each time. Tree stops growing on switch release.
  • Mic Sensor = Conditionals placed on the mic made it sensitive to close-contact blowing which resulted in visually seeing the tree move and contort rapidly with colour change.
  • Force Sensor = Touching the force sensor resulted in what was supposed to be a physical exchange between user and tree–shown by lighting up the tree in an orange and red colour scheme…depicting warmth…life energy. The sensor was conditioned accept moderately forceful touches.

Future Iteration 

I would definitely work on creating a unique and appropriate physical interface to further contribute to immersion and presence in regards to the visual piece and all that it conveys. I was planning to create a small tree trunk which would house the Arduino device and have sensors incorporated into its body. Play-Doh seems like an interesting material to experiment with in creating such an object. The use of video tracking, which I was also heavily relying on in my initial concept formulation, would be great. I was hoping to have the user guide the tree’s X position based on their left/right position in front of the screen…almost as to provide the user with fictional shade and distance from the screen controlling the location of the tree on the Z axis.

DEMO

Arduino Code

//DIGF 6B02: Creation & Computation
//Final Project, November 2011
//by Harjot Bal
//LIVING TREE
//Arduino Code
//A combination of Processing and Arduino were used to allow users to interact physically with a digital tree.

//Declare serial input variables.
const int mic = A0;
const int pot = A2;
const int force = A5;

void setup() {

//Set baud rate for capture.
Serial.begin(115200);

}

void loop() {

  //Print and read analog values that are coming in, split each by use of commas.
  Serial.print(analogRead(mic));
  Serial.print(",");
  Serial.print(analogRead(pot));
  Serial.print(",");
  Serial.println(analogRead(force));

}

Processing Code

//DIGF 6B02: Creation & Computation
//Final Project, November 2011
//by Harjot Bal
//LIVING TREE
//Processing Code
//A combination of Processing and Arduino were used to allow users to interact physically with a digital tree.
//Reference: http://blog.superkrut.se/data/tree/applet/sketch_050113a.pde - Superkrut's processing tree code helped me in building the tree structure.
//Reference: Background image used was royalty-free via http://www.sxc.hu/.
//Reference: Music track "Wounded.mp3" used was royalty-free via http://incompetech.com/.

//Call Minim library for audio.
import ddf.minim.*;
//Start AudioPlayer via Minim.
Minim minim;
AudioPlayer player;
//Decalre a variable for graphic to be imported.
PImage b;
//Call Serial library for serial inputs.
import processing.serial.*;
//3 serial inputs used (shown as variables). Note: "pot" can be replaced with a switch.
float mic = 0;
float pot = 0;
float force = 0;
//Declare serial class.
Serial myPort;
//Variable for a new tree root is set to 0.
int nr=0;
//Declare the body part to be made.
BodyPart root;
//Variable for where the base of the tree starts, can be changed in terms of dimensions.
float rootAngleX=1500;
float rootAngleY=0;

void setup() {

  //Size of screen, with call to 3D library.
  size(1400, 800, P3D);
  //New audio object via Minim.
  minim = new Minim(this);
  //Call track which is located inside data folder.
  player = minim.loadFile("Wounded.mp3", 1024);
  //Play the audio (on Run of sketch).
  player.play();
  //Color mode used with range of 1.
  colorMode(RGB, 1);
  //Define the background image via the variable b, image to be located in data folder.
  b = loadImage("pic.jpg");
  //Root object setup.
  root = new BodyPart(0, 0);
  //List all the available serial ports
  println(Serial.list());
  myPort = new Serial(this, Serial.list()[0], 115200);

}

void draw() {

  //Call 'b' image through background.
  background(b);
  //Lights up the 3D cylinders used in the tree baed on orientation.
  lights();
  //move base of tree, according to 3D plane. X, Y, and Z axes.
  translate(width/2, height,-50);
  //Rotate base so that it is upward.
  rotateX(rootAngleX/1000);
  rotateZ(rootAngleY/1000);
  //Call the function which starts growth of the tree.
  root.grow();
  //Under the root growing function set to angle position of cylinders to 0.
  root._angPosX = 0;

}

//Define the body part class with all required variables.
class BodyPart {
  BodyPart[] children = new BodyPart[3];
  //New root.
  private int child_nr=0;
  //Width of tree.
  private float _width = 0;
  //Height of tree.
  private float _height = 0;
  //How fast tree grows horizontally.
  private float _widthspeed;
  //How fast tree grows vertically.
  private float _heightspeed;
  //Openness of tree branches of X plane.
  private float _angleX;
  //Openness of tree branches of X plane.
  private float _angleY;
  //Variable created for manipulating 'mic' input. The wind factor.
  public float brandnewX;
  //The affected variable as a result of 'mic' input.
  public float _angPosX;
  //Range of angles for tree branches on X plane.
  private float newangleX;
  //Range of angles for tree branches on Y plane.
  private float newangleY;
  //Dictates when to grow new beanches.
  private float nextchild;

//Inputs values to tailor growth of tree.
public BodyPart(float angleX, float angleY){
    //Initial varaibles defined.
    _angleX = angleX;
    _angleY = angleY;
    _angPosX = 0;
    _widthspeed=.04;
    _heightspeed=.3;
    nextchild = 2;
  }

//Tree development while growing handled here.
public void grow(){
    //If swith is pushed or potentiometer is turned...GROW!
    if(pot == 0){
      //Default tree color.
      fill(.3,.3,.3,.9);
      //Vertical growth.
      _height+=_heightspeed;
      //Horizontal growth.
      _width+=_widthspeed;
      //Conditional for when to grow a new "child" (branch). Dependent on width of previous cylinder and numbers of branches it has thus far.
      if(_width>nextchild && child_nr<2){
        //Random branch growth, highest the cylinders can stack is 20x vertically.
        nextchild+=random(1,20)*(child_nr+1);
        //Vertical growth occurs at an addition of 40% current rate.
        _heightspeed*=.4;
        //Randomized range for openness of branches on X plane.
        newangleX = random(.2,.4);
        //Randomized range for openness of branches on X plane.
        newangleY = random(.2,.8);
        //Imput randomized growth values and use them for each new child or branch grown.
        children[child_nr++] = new BodyPart(random(-newangleX,newangleX), random(-newangleY,newangleY));
  }
    } 

    //Call the function that colors the tree.
    paint();

    //Keep tree growing in respect to current branches.
    for(int i = 0;i<child_nr;i++){
      pushMatrix();
      children[i].grow();
      popMatrix();
    }

}

//Draw each cylinder according to input values.
void drawCylinder(float topRadius, float bottomRadius, float tall, int sides) {

  //3D cyinder shape creation
  float angle = 0;
  float angleIncrement = TWO_PI / sides;
  beginShape(QUAD_STRIP);
  for (int i = 0; i < sides + 1; ++i) {
    vertex(topRadius*cos(angle), 0, topRadius*sin(angle));
    vertex(bottomRadius*cos(angle), tall, bottomRadius*sin(angle));
    angle += angleIncrement;
  }
  endShape();
  //Rotate the cylinder according to tree once made.
  rotateX(-PI/2);

}

private void paint(){  

    //Color of tree, grayish.
    fill(.3,.3,.3,.9);
    //Darkened tips of branches.
    stroke(2);
    strokeWeight(2);

    //Movement of branches and everything connected to them, again oriented to tree position.
    rotateX(_angleX+sin(brandnewX)/10+PI/2);
    rotateY(_angleY+sin(brandnewX)/10);

    //If the force sensor is pushed alone, detecting a value less than 200, change of color and transparency!
    if(force <= 200 && pot !=0 && force !=0){
      fill(_width/10,_width/15,random(.2,.3),random(.4,.6));
    }
    //Or else do this.
    else{
     //Left out for now!!
     // fill(_width/30,random(.3,.4),random(.3,.4)/*,random(.3,.4)*/);
    }
    //If mic senses sound out of the range of a certain threshold only then chnage the speed of random movement of the tree branches.
    if(mic > 444 && mic < 459){
      //Within set range, so don't change branch movement.
      brandnewX = _angPosX+=.05/_width;
    }
    //The WIND factor!
    else{
      //change number value to increase/decrease amount of wind perceived.
      brandnewX = _angPosX+=5/_width;
      //Colorize the tree when wind is present.
      fill(random(.4,.5),random(.7,.8),_width/10,random(.4,.5));
    }
    //The values for drawing each cylinder.
    drawCylinder(_width/1.5, _width/1.5, _height, 10);
    //Placement of cylinder in respect to tree.
    translate(0,0,_height);
   }

}

//Dial in the serial values.
void serialEvent (Serial myPort) {

  //Read port until new values stop coming in.
   String inString = myPort.readStringUntil('\n');
  //Ignore anything that isn't a value.
   if (inString != null) {
  //Trim off any whitespace.
   inString = trim(inString);
  //Split the string on the commas and convert the resulting substrings into an integer array.
   float[] input = float(split(inString, ","));
  //If the array has at least three elements, you know you got the whole thing.
   if (input.length >=3) {
  //Map the values to any range desired.
   mic = map(input[0], 0, 1023, 0, 1023);
   pot = map(input[1], 0, 1023, 0, 1023);
   force = map(input[2], 0, 1023, 0, 1023);
   }
  }

}

//Stop the music.
void stop() {

  //Closes Minim audio classes when done with them.
  player.close();
  minim.stop();

  super.stop();
}


Comments are closed.