Sunday, 31 January 2010
Colour Variations....
I have been experimenting with the colour of the observation unit to see what best fits its form & function. So far I am more inclined to use blue as it is cold, but strangely welcoming. I'm also interested in the dark grey (but the only problem with this is that most designers use black, grey & white & I don't want to blend in with the crowd...).
Saturday, 30 January 2010
Industrial Facility
I really like the simple aesthetics of Industrial Facility- clean lines with a limited colour scheme. I think it might be too simple for the style of my product. I want to have some nice details on it with possibly contrasting colours to make it more interesting.
Sketches
The Observer
Just a quick (fictional) example of people who take recording to the extreme - "The Observer", from the sci-fi television series Fringe.
Language
Friday, 29 January 2010
Peep Rig MK V.
Hero Code
import processing.video.*; // import theProcessing video library
import processing.serial.*; // import the Processing serial library
static final boolean USE_ARDUINO = true;
static final boolean USE_WEBCAM = false;
static final String WEBCAM_STRING = "USB PC Camera-WDM";
static final int MAX_LOAD_ATTEMPTS = 15; // Number of times to try loading a web image
static final String[] feedSetup = new String[] {
"Adelaide Market Observer", "http://www.adelaidecitycouncil.com/netcatapps/webcam/images/centralMkt.jpg", // Adelaide Market
"Vancouver Observer", "http://www.cbc.ca/bc/webcam/images/webcam.jpg", // Vancouver Building Site
"Adelaide Lantern Observer", "http://www.adelaidecitycouncil.com/netcatapps/webcam/images/rundleEast.jpg", // Rundle Mall East & Lantern
"Colony Observer", "http://www.draperbee.com/webcam/pic/image.jpg?1262444320177", // Beehive
"Adelaide 3 Observer", "http://www.adelaidecitycouncil.com/NetcatApps/webcam/images/bellsth.jpg", // Adelaide Bell Street South
"Aruba Observer", "http://www.bucuticam.com/arubacam.jpg", //Aruba, Netherlands Antilles
"Turtle Dome Observer", "http://www.yosemite.org/DSN/wwwyosemiteassociationorg/Content/Webcam/turtleback.jpg", //Yosemite, Turtle Dome
"Brooklyn Bridge Observer", "http://brooklyn-bridge.mobotixcam.de/record/current.jpg?rand=380424", //Brooklyn Bridge
"Bass Rock Observer", "http://www.outercam.co.uk/ssc/camera3.jpg?1260446915311", // Bass Rock, North Berwick
"Bar Observer", "http://ecoast.vs.oiccam.com:443/ftp/capcom/jackalope/image.jpg?rand=14:52:10", //Jackalope Jacks Bar, North Carolina
"Panama Canal Observer", "http://webcams.pancanal.com/webcam/miraflores.jpg", // Panama Canal
"Dundee Satellite Observer", "http://www.sat.dundee.ac.uk/webcam/cam0.jpg", //Dundee Tower Building
"Living Room Observer", "http://www.xs4all.nl/~twocats/cam/Cam-A.jpg", //Amsterdam House
"Ablerta University Observer", "http://www.cs.ualberta.ca/~lake/cam/jpg/large/201.jpg", //Alberta University
"Drama Observer", "http://facweb.furman.edu/~rbryson/dramadept/TheatreCamPic.jpg", //Student Theatre
};
Serial Arduino; // The serial port
//boolean onoff = true; // Display the local webcam?
PFont font; // Description text font
// Feeds, current feed index and reference for current feed (from the ArrayList)
private ArrayList feeds;
int feedIndex; // Current feed index
int camIndex = -1; // Index of cam (if available)
Feed currentFeed;
float xpos, ypos, onoff; // Starting position of the webcam feed
float specialWidth = 1450.0;
float scrollOffset = 0; // Text scrolling offset
float scrollSpeed = 3; // Text scrolling speed
int scrolltext;
long clock; // Realtime clock in milliseconds, based on millis(), updated in ticktock()
void setup()
{
ticktock();
size(1050,760,P3D);
font = loadFont("Consolas-36.vlw");
textFont(font, 36);
if (USE_ARDUINO && !online)
{
// List all the available serial ports
println(Serial.list());
Arduino = new Serial(this, Serial.list()[1], 9600);
// read bytes into a buffer until you get a linefeed (ASCII 10):
Arduino.bufferUntil('\n');
}
feeds = new ArrayList();
if (USE_WEBCAM && !online) try
{
// List all the available cameras
println(Capture.list());
CaptureFeed captureFeed = new CaptureFeed(this, "Camera One", WEBCAM_STRING, width/2, height/2, 30);
camIndex = feeds.size();
feeds.add(captureFeed);
}
catch (Exception e)
{
println("Error initialising webcam (" + WEBCAM_STRING + "): " + e.getMessage());
}
// Set up web feeds
for (int i = 0; i <>
{
Feed feed = new WebFeed(feedSetup[i], feedSetup[i+1]);
feeds.add(feed);
}
selectFeed(0); // Maybe webcam
}
void draw()
{
ticktock();
background(0);
rotate(-PI/2);
scrollOffset += scrollSpeed;
if (scrollOffset > width + specialWidth)
{
scrollOffset = 0;
}
currentFeed.update();
currentFeed.display();
if(onoff == 0){
background(0);
}
}
public void ticktock()
{
clock = millis();
}
void serialEvent(Serial Arduino)
{
// Read the serial buffer:
String myString = Arduino.readStringUntil('\n');
// if you got any bytes other than the linefeed:
if (myString != null){
myString = trim(myString);
// split the string at the commas
// and convert the sections into integers:
int sensor[] = int(split(myString, ','));
// print out the values you got:
for (int sensorNum = 0; sensorNum <>
print("sensor " + sensorNum + ": " + sensor[sensorNum] + "\t");
}
// add a linefeed after all the sensor values are printed:
println();
if (sensor.length > 1){
xpos = map(sensor[0], 0, 1023, -width/2, -(width/4)*3);
ypos = map(sensor[1], 0, 1023, 0, (height- 150 - height/2));
int feedSelection = constrain((int)map(sensor[2], 0, 1023, 0, feeds.size() - 1), 0, feeds.size() - 1);
selectFeed(feedSelection);
onoff = map(sensor[3], 0, 1, 0, 1);
if (onoff == 1)
{
selectFeed(camIndex);
}
scrolltext = (int)map(sensor[4], 0, 1023, 0, currentFeed.description.length() - 1);
}
}
}
void displayScrollText(String displayText)
{
text(displayText, width - scrollOffset, height + 200);
}
public void selectFeed(int feedSelection)
{
if (feedSelection <>= feeds.size())
{
println("Cannot select feedIndex " + feedSelection);
return;
}
feedIndex = feedSelection;
currentFeed = (Feed)feeds.get(feedIndex);
}
//============================================================
/**
* Feed class
* Contains feed metadata (description and locator) and
* proscription for update() and display() methods in subclasses
*/
abstract class Feed
{
public String description;
public String locator;
public Feed(String description, String locator)
{
this.description = description;
this.locator = locator;
}
public abstract void update(); // Must be implemented in subclasses
public abstract void display(); // Must be implemented in subclasses
}
//============================================================
/**
* WebFeed class
* Access periodically-updated image from the web
* Load image in separate thread so as not to block main thread
* Delayed refresh (after error or sucessful load)
*/
class WebFeed extends Feed
{
public int refreshDelay = 2000; // Number of milliseconds to wait between refresh() calls
public PImage loadedImage; // Last loaded image
private PImage loadingImage; // Used for requestImage()
private boolean loading; // Waiting for result from requestImage()?
private boolean requestRefresh; // Set true when a refresh() is wanted
private long refreshAt; // Time (based on millis()) at which to refresh() if requestRefresh true
private int loadFailures; // Number of times the load has failed (since last successful load)
public WebFeed(String description, String locator)
{
super(description, locator);
println("new WebFeed(" + description + ", " + locator + ")");
loadedImage = null;
refresh();
}
public void update()
{
if (loading)
{
if (loadingImage.width == 0)
{
// Image is not yet loaded
}
else if (loadingImage.width == -1)
{
// This means an error occurred during image loading
println("requestImage() failed for " + description + " [" + locator + "]");
loading = false;
loadFailures++;
if (loadFailures <>
{
requestRefresh();
}
}
else
{
// Image is loaded; save a copy and request a fresh copy
println("Loaded: " + description);
loadedImage = loadingImage;
loading = false;
loadFailures = 0;
requestRefresh();
}
}
if (requestRefresh && clock >= refreshAt)
{
refresh();
}
}
public void requestRefresh()
{
requestRefresh = true;
refreshAt = clock + refreshDelay;
println("refreshAt: " + refreshAt + " (now: " + clock + ")");
}
public void refresh()
{
println("Refresh " + description + " [" + locator + "]");
loadingImage = requestImage(locator);
loading = true;
requestRefresh = false;
}
public void display()
{
if (loadedImage == null)
{
displayScrollText(description + " LOADING...");
}
else
{
image(loadedImage, xpos, ypos, width/2, height/2);
displayScrollText(description + " ONLINE");
}
}
}
//============================================================
class CaptureFeed extends Feed
{
public Capture capture; // A local webcam
public CaptureFeed(PApplet p5, String description, String locator, int feedWidth, int feedHeight, int fps)
{
super(description, locator);
capture = new Capture(p5, feedWidth, feedHeight, locator, fps);
}
public void update()
{
if (capture.available())
{
capture.read();
}
}
public void display()
{
image(capture, xpos, ypos);
displayScrollText(description + " LIVE");
}
}
Deciding not to use "live" webcams
Wednesday, 27 January 2010
Rationale Revised
I am designing a observation unit for remote viewing & the collection of information. I am designing it for people who have a compulsion for recording everything they see. The object is a critique of people having access of watching the world , the implications of it & if the user would develop a bond with the content.
I think it's sounding pretty good!
Code Development
import processing.video.*; // import theProcessing video library
import processing.serial.*; // import the Processing serial library
Serial Arduino; // The serial port
Capture webCamOne; // The webcam feed
Capture webCamTwo;
PFont font;
float xpos, ypos, manualauto, x; // Starting position of the webcam feed
int autoselect, manualselect;
float size = 700.0;
String[] feed = new String[] {
"http://www.adelaidecitycouncil.com/netcatapps/webcam/images/centralMkt.jpg", //Adelaide Market
"http://www.cbc.ca/bc/webcam/images/webcam.jpg", // Vancouver Building Site
"http://www.adelaidecitycouncil.com/netcatapps/webcam/images/rundleEast.jpg", //Rundle Mall East & Lantern
"http://www.draperbee.com/webcam/pic/image.jpg?1262444320177", //beehive
"http://www.adelaidecitycouncil.com//NetcatApps/webcam/images/bellsth.jpg" //Adelaide Bell Street South
};
String[] description = new String[]{
"Adelaide 1 Observer ONLINE",
"Vancouver Observer ONLINE",
"Adelaide 2 Observer ONLINE",
"Colony Observer ONLINE",
"Adelaide 3 Observer ONLINE",
};
PImage[] images;
void setup() {
size(678,510,P3D);
font = loadFont("01_Digit-23.vlw");
textFont(font, 23);
// List all the available serial ports & cameras
//println(Serial.list());
println(Capture.list());
webCamOne = new Capture(this, width/2, height/2, "USB PC Camera-WDM", 30);
webCamTwo = new Capture(this, width/2, height/2, "PC Camer@-WDM", 30);
Arduino = new Serial(this, Serial.list()[1], 9600);
// read bytes into a buffer until you get a linefeed (ASCII 10):
Arduino.bufferUntil('\n');
/ need as many images as we have feeds
images = new PImage[feed.length];
// initial load of images (slow);
for (int i = 0 ; i <>
images[i] = loadImage(feed[i]);
}
}
void draw() {
background(0);
if (manualauto == 1){
if (manualselect == 0){
if (webCamOne.available()){
webCamOne.read();
}
image(webCamOne, xpos, ypos);
translate(-x, 0, 0);
text("OBSERVER 1 ONLINE", 0, 494);
}
if (manualselect == 1){
if (webCamTwo.available()){
webCamTwo.read();
}
image(webCamTwo, xpos, ypos);
translate(-x, 0, 0);
text("OBSERVER 2 ONLINE", 0, 494);
}
if (manualselect == 2){
translate(-x, 0, 0);
text("OBSERVER 3 OFFLINE", 0, 494);
}
}
else{
loadImage(feed[autoselect]);
image(images[autoselect], xpos, ypos, width/2, height/2);
translate(-x, 0, 0);
text(description[autoselect], 0, 494);
}
x = x +3;
if (x > width + size){
x = -size;
}
}
void serialEvent(Serial Arduino) {
// read the serial buffer:
String myString = Arduino.readStringUntil('\n');
// if you got any bytes other than the linefeed:
if (myString != null) {
myString = trim(myString);
// split the string at the commas
// and convert the sections into integers:
int sensor[] = int(split(myString, ','));
// print out the values you got:
for (int sensorNum = 0; sensorNum <>
print("sensor " + sensorNum + ": " + sensor[sensorNum] + "\t");
}
// add a linefeed after all the sensor values are printed:
println();
if (sensor.length > 1) {
xpos = map(sensor[0], 0, 1023, 0, width/2);
ypos = map(sensor[1], 0, 1023, 0, (height/2 - 50));
autoselect = (int)map(sensor[2], 0, 1023, 0, images.length - 1);
manualauto = map(sensor[3], 0, 1, 0, 1);
manualselect = (int)map(sensor[4], 0, 1023, 0, 2);
}
}
}
On Top Form
After a little deliberation, the class decided that the main identifiers of the products in question were:
Boxy, modular, simple, basic, bland..., clinical, highlight colours, sheet metal, cold, laboratory, pseudo-scientific, 1950's, modernism, form follows function, honest.
& the main characteristics were:
Masculine, modern, serious, expensive, technology, science, rational.
We then had to try to mix two of the words together to sum up my personal stlye.
So far I've got 50's Pseudo Tech - still working on it...
The Curious Home
After talking to one of my lecturers about the form of my object, reminded me about The Curious Home project at Goldsmiths in London, in particular, the Local Barometer. Their forms are very basic, but honest - they do what they look like they will do, display information. I want my product to have these qualities, but have a darker look to it...
Monday, 25 January 2010
Brains & ...
Friday, 22 January 2010
The Lives of Others/Stasi Objects
I was recommended to watch the film "The Lives of Others" for the style the observation unit that I will be making, & found it very inspirational - both in the objects & the story. I want the user of the product to build a deep relationship with the content via the interaction of the object - starting with an ordinary, even obligatory usage to developing an emotional bond with the machine, letting them live out someone else's life through it.
After watching the film, I want the object to look very functional & serious - harsh lines & no curves, with an array of different, but identical looking buttons & dials, so the user has to learn how to manipulate the machine (creating the first step to developing a bond).
Here are some pictures of German Stasi (Secret Police) surveillance objects from the 1980's - just through the way they look, they feel cold, calculated...
Wednesday, 20 January 2010
Lenses
Just some quick experiments with a small selection of lenses :
A 3.5x zoom diamond viewer
A 20x zoom pocket magnifier
A wallet variable magnifier
The result was that the wallet magnifier performed the best - as it was completely flat & was consistently easier to focus the webcam with than the other two.
Directives
PFont font;
float x;
float size = 430.0;
// The font must be located in the sketch's
// "data" directory to load successfully
void setup(){
size(600, 100, P3D);
font = loadFont("SubwayTicker-32.vlw");
textFont(font, 23);
}
void draw(){
background(0);
x = x +3;
if (x > width + size){
x = -size;
}
translate(x, 0, 12);
text("Directive 1: Mid-life transitions", 0, 44);
}
The only problem with the Mass Observation is that the topics are very broad & not a lot of deliberate observation is needed, mostly past experiences. I want the user to interact with the object as if it is necessary for the completion of the "mission". Maybe the content of the directives need to be customised...
The code so far...
Arduino:
int potpinx = 0; //analog input
int potpiny = 1; //analog input
int potpinzoom = 2; //analog input
int onoff = 3; //digital input
int scroll = 5; //analog input
int onoffled = 13; // digital output
int sensorValue = 0; //analog value
int onoffvalue = 0; //digital value
void setup() {
// configure the serial connection:
Serial.begin(9600);
// configure the digital input
pinMode(onoff, INPUT);
// configure the digital output
pinMode(onoffled, OUTPUT);
}
void loop() {
// read the sensor:
sensorValue = analogRead(potpinx);
// print the results:
Serial.print(sensorValue, DEC);
Serial.print(",");
// read the sensor:
sensorValue = analogRead(potpiny);
// print the results:
Serial.print(sensorValue, DEC);
Serial.print(",");
// read the sensor:
sensorValue = analogRead(potpinzoom);
// print the results:
Serial.print(sensorValue, DEC);
Serial.print(",");
// read the sensor:
sensorValue = digitalRead(onoff);
Serial.print(sensorValue, DEC);
Serial.print(",");
//read the sensor:
sensorValue = analogRead(scroll);
Serial.println(sensorValue/255, DEC);
delay(90);
//read the onoff switch again & assign the output as a different name
onoffvalue = digitalRead(onoff);
//if the digital switch is in the on position, turn on the led
if (onoffvalue == HIGH){
digitalWrite(onoffled, HIGH);
}
else{
digitalWrite(onoffled, LOW);
}
}
Processing:
import processing.video.*; // import theProcessing video library
import processing.serial.*; // import the Processing serial library
Serial Arduino; // The serial port
Capture webCam; // The webcam feed
PImage hide; //Declare variable "hide" of type PImage
float xpos, ypos, zoom, onoff; // Starting position of the webcam feed
void setup() {
size(640,480,P3D);
// List all the available serial ports & cameras
//println(Serial.list());
//println(Capture.list());
webCam = new Capture(this, width/2, height/2, "USB PC Camera-WDM", 30);
Arduino = new Serial(this, Serial.list()[1], 9600);
// read bytes into a buffer until you get a linefeed (ASCII 10):
Arduino.bufferUntil('\n');
}
void draw() {
background(153, 153, 0);
scale(zoom/100);
if (webCam.available()){
webCam.read();
}
if (onoff == 1){
image(webCam, xpos, ypos);
}
}
void serialEvent(Serial Arduino) {
// read the serial buffer:
String myString = Arduino.readStringUntil('\n');
// if you got any bytes other than the linefeed:
if (myString != null) {
myString = trim(myString);
// split the string at the commas
// and convert the sections into integers:
int sensor[] = int(split(myString, ','));
// print out the values you got:
for (int sensorNum = 0; sensorNum <>
print("sensor " + sensorNum + ": " + sensor[sensorNum] + "\t");
}
// add a linefeed after all the sensor values are printed:
println();
if (sensor.length > 1) {
xpos = map(sensor[0], 0,width,0,width);
ypos = map(sensor[1], 0,height,0,height);
zoom = map(sensor[2], 1, 1023, 1, 1023);
onoff = map(sensor[3], 0, 1, 0, 1);
}
}
}
New Interactions
As I want some of the interactions of my product to be microscope-ish, I wanted to use potentiometers to control some aspects of the image on screen - such as moving the feed on the x & y axis, & changing the scale of the picture (as well as turning the feed on & off).
Instead of using Pure Data as I originally thought, I have managed to use an Arduino board & Processing. The video of the system working is below:
Early Form Prototype
Here are a couple of pictures of the original form of the observation unit - I wanted the aesthetics to be very simple & angular (to be slightly threatening, as if you shouldn't be looking into it).
The whole idea of this shape was so you could put your whole head into it to totally immerse yourself in the experience - along with the web feed, surround sound would make you feel like you were in the room with the "subject".
Mass Observation Project
"The Mass Observation Project (MOP) is a unique UK-based writing project which has been running since 1981. It exists to:
- Provide a structured programme within which “ordinary” people can write directly about their lives in the knowledge that what they send in will be archived for posterity and used for social research
- Create a resource of qualitative longitudinal social data with an emphasis on subjectivity and self representation which will contribute to our understanding of everyday life in the late 20th and early 21st century.
The MOP differs from other similar social investigations because of its historical link to the original Mass Observation and because of its focus is on voluntary, self-motivated participation. It revives the early Mass Observation notion that everyone can participate in creating their own history or social science. The Mass Observers do not constitute a statistically representative sample of the population but can be seen as reporters or “citizen journalists” who provide a window on their worlds.
The material is solicited in response to “Directives” or open-ended questions sent to them by post or email three times a year. The Directives contain two or three broad themes which cover both very personal issues and wider political and social issues and events. Over 4,000 people have taken part to date, many of them corresponding over several years.
The collection comprises in-depth accounts (both opinion and experience) of everyday life: stories, memoirs, lists, letters, diagrams, drawings, maps, diaries, photographs, press cuttings, confessions, reports on people, places and events, across a wide variety of topics."This seems to be the perfect outlet for my product - a tool for the studying of society. I just need to alter my rationale to fit in with this type of activity...