Mirrorshades project – video of camera test

A quick video of me testing the Mirrorshades setup at my desk, with 2.5mm lenses fitted to the cameras. More info in the video description on YouTube.

Mirrorshades project – Oculus Rift, 2x PlayStation Eye cameras, Unity

Continuing my cross reality research, I’m working on an Oculus Rift project to allow you to switch/fade between your real surroundings & virtual surroundings. I’m using 2x PlayStation Eye webcams (cheap, 60fps, easy to fit with standard M12 lens mounts so you can use all sorts of different lenses – I’m using 2.5mm lenses atm) attached to the Rift via a 3D printed mount & with Unity on the software end using code from this chap (Japanese link) because Unity’s WebCamTexture doesn’t work with 2x identical cameras.

IMG_20131112_173613

The mount comprises the clip designed by the guys at USC Information Technology Services (& freely downloadable from their website) with a second piece I designed & glued onto the front with epoxy. I found an EAGLE board file for the webcams so was able to design this second piece with channels matching the PCB mounting holes, allowing the webcams to be moved horizontally to experiment with different interpupillary distances (or even to completely remove one camera & simply position the remaining one in the centre).

IMG_20131112_173813

One of the cameras has to be upside down because the width of the top of the PCBs (where the mic array is) means that they can’t be placed close enough together when they are both the same way up! The image from the upside-down camera is just rotated in software.

IMG_20131112_182603

IMG_20131112_160240

IMG_20131112_173718

IndoorAtlas Beta – track phone from another device

As you may have seen on YouTube I’ve recently been experimenting with the beta of IndoorAtlas, a service that allows a smartphone to use its magnetometer to determine its position within a building by measuring fluctuations to the Earth’s magnetic field caused by metal building materials;

I’m not so much interested in using IndoorAtlas to make a location aware smartphone app, but instead in using it to provide indoor positioning to a Unity application that displays to an Oculus Rift. To do this I had to make the positioning data available to devices other than the phone itself; the IndoorAtlas API allows a device to obtain its own position, but not to make this position available to other devices (obviously there are privacy concerns involved here!).

So as a quick hack (I believe the research term is ‘proof of concept’) I modified the example Eclipse project that comes with the IndoorAtlas Android API download to additionally submit the position data that the phone receives to a MySQL database on one of my servers, which can then be accessed by whatever I see fit. I borrowed a lot of code from here.

On the phone, it’s simply a case of editing the onServiceUpdate method to build a HTTP POST (with the relevant data as POST parameters) & to send it to a piece of server side PHP which adds or updates the details for the particular phone to the database. The PHP looks something like this;

<?php

// array for JSON response
$response = array();

// check for required fields in POST data
if (isset($_POST['deviceId']) && isset($_POST['buildingId']) && isset($_POST['levelId']) && isset($_POST['floorplanId']) && isset($_POST['latitude']) && isset($_POST['longitude']) && isset($_POST['x']) && isset($_POST['y'])	&& isset($_POST['i']) && isset($_POST['j']) && isset($_POST['heading']) && isset($_POST['probability']) && isset($_POST['roundtrip']) && isset($_POST['time'])) {

	// extract data from POST into variables
	$deviceId = $_POST['deviceId'];
	$buildingId = $_POST['buildingId'];
	$levelId = $_POST['levelId'];
	$floorplanId = $_POST['floorplanId'];
	$latitude = $_POST['latitude'];
	$longitude = $_POST['longitude'];
    $x = $_POST['x'];
    $y = $_POST['y'];
    $i = $_POST['i'];
    $j = $_POST['j'];
    $heading = $_POST['heading'];
    $probability = $_POST['probability'];
	$roundtrip = $_POST['roundtrip'];
    $time = $_POST['time'];

	// include database connect class
	require_once __DIR__ . '/db_connect.php';

 	// connect to the database
 	$db = new DB_CONNECT();

	// check whether primary key already exists
	$result = mysql_query("SELECT * FROM devicelocations WHERE deviceId = '$deviceId';");
	$arr = mysql_fetch_array($result);

	// If the select statement returns the empty set, sizeof will return 1. Otherwise sizeof will return 28 (14 columns in a row).

	// if the deviceID does not already exist in the database, do an INSERT
	if (sizeof($arr) == 1) {
		$result = mysql_query("INSERT INTO devicelocations (deviceId, buildingId, levelId, floorplanId, latitude, longitude, x, y, i, j, heading, probability, roundtrip, time) VALUES ('$deviceId', '$buildingId', '$levelId', '$floorplanId', '$latitude', '$longitude', '$x', '$y', '$i', '$j', '$heading', '$probability', '$roundtrip', '$time');");
	}
	// if the deviceID does already exist in the database, do an UPDATE
	else {
		$result = mysql_query("UPDATE devicelocations SET buildingId = '$buildingId', levelId = '$levelId', floorplanId = '$floorplanId', latitude = '$latitude', longitude = '$longitude', x = '$x', y = '$y', i = '$i', j = '$j', heading = '$heading', probability = '$probability', roundtrip = '$roundtrip', time = '$time' WHERE deviceId = '$deviceId';");
	}

    // check if row inserted or not
    if ($result) {
        // successfully inserted into database
        $response["success"] = 1;
        $response["message"] = "Entry successfully inserted or updated.";

        // echoing JSON response
        echo json_encode($response);
    } else {
        // failed to insert row
        $response["success"] = 0;
        $response["message"] = "Entry was not successfully inserted or updated.";

        // echoing JSON response
        echo json_encode($response);
    }

} else {
    // required POST field is missing
    $response["success"] = 0;
    $response["message"] = "Required POST field(s) missing";

    // echoing JSON response
    echo json_encode($response);
}

?>

Once the data are in the database, I can access them from pretty much anything I want. As a quick test I put together a simple Web page that displays the floor plan image with a red dot to represent the phone’s last known location as well as dumping the data in text form;

map

The PHP for this page looks something like this (it’s a quick hardcoded hack, but you get the idea);

<?php

echo "<head>";
echo "<meta http-equiv='refresh' content='2.5'>";
echo "</head>";

require_once __DIR__ . '/db_connect.php';

$db = new DB_CONNECT();

$result = mysql_query("SELECT * FROM devicelocations");

$arr = mysql_fetch_array($result);

$deviceId = ($arr[0]);
$buildingId = ($arr[1]);
$levelId = ($arr[2]);
$floorplanId = ($arr[3]);
$latitude = ($arr[4]);
$longitude = ($arr[5]);
$x = ($arr[6]);
$y = ($arr[7]);
$i = ($arr[8]);
$j = ($arr[9]);
$heading = ($arr[10]);
$probability = ($arr[11]);
$roundtrip = ($arr[12]);
$time = ($arr[13]);

echo "<div style='position: relative; left: 0; top: 0;'>";
echo "<img src='map.gif' style='position: relative; top: 0; left: 0;'/>";
echo "<img src='splodge.png' width = 1% style='position: absolute; top: ";
echo ($j)/10;
echo "; left: ";
echo ($i)/10;
echo ";'/>";
echo "</div>";

echo "deviceId: ";
echo $deviceId;
echo "<br/>";
echo "buildingId: ";
echo $buildingId;
echo "<br/>";
echo "levelId: ";
echo $levelId;
echo "<br/>";
echo "floorplanId: ";
echo $floorplanId;
echo "<br/>";
echo "latitude: ";
echo $latitude;
echo "<br/>";
echo "longitude: ";
echo $longitude;
echo "<br/>";
echo "x: ";
echo $x;
echo "<br/>";
echo "y: ";
echo $y;
echo "<br/>";
echo "i: ";
echo $i;
echo "<br/>";
echo "j: ";
echo $j;
echo "<br/>";
echo "heading: ";
echo $heading;
echo "<br/>";
echo "probability: ";
echo $probability;
echo "<br/>";
echo "roundtrip: ";
echo $roundtrip;
echo "<br/>";
echo "time: ";
echo $time;

?>

Next will be to modify a player/camera controller in Unity so that it moves according to the position of the phone!

unity