<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Gaurav Manek&#039;s Blog</title>
	<atom:link href="http://www.gauravmanek.com/blog/?feed=rss2" rel="self" type="application/rss+xml" />
	<link>http://www.gauravmanek.com/blog</link>
	<description></description>
	<lastBuildDate>Tue, 29 Nov 2011 14:44:04 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>Review: Densitron DD-6448BE-2A (OLED panel)</title>
		<link>http://www.gauravmanek.com/blog/?p=53</link>
		<comments>http://www.gauravmanek.com/blog/?p=53#comments</comments>
		<pubDate>Tue, 29 Nov 2011 14:16:49 +0000</pubDate>
		<dc:creator>gauravmm</dc:creator>
				<category><![CDATA[Projects]]></category>
		<category><![CDATA[technical]]></category>

		<guid isPermaLink="false">http://www.gauravmanek.com/blog/?p=53</guid>
		<description><![CDATA[The good folks over at element14 sent me a really, really small OLED display for an upcoming project. The Densitron DD-6448BE-2A with the accompanying evaluation board. It&#8217;s a blue/black OLED screen, 64 pixels wide by 48 pixels high with good visibility and pretty decent contrast. It uses 3V logic, but needs a 9V supply to drive the display. Here&#8217;s [...]]]></description>
			<content:encoded><![CDATA[<p>The good folks over at <a href="http://element14.com" target="_blank">element14</a> sent me a really, really small OLED display for an upcoming project. The <a href="http://sg.element14.com/densitron/dd-6448be-3a/display-oled-64x48-blue/dp/1498838" target="_blank">Densitron DD-6448BE-2A</a> with the <a href="http://sg.element14.com/densitron/evk-connect-013/connection-board-for-1498838-evk/dp/1500760" target="_blank">accompanying evaluation board</a>. It&#8217;s a blue/black OLED screen, 64 pixels wide by 48 pixels high with good visibility and pretty decent contrast. It uses 3V logic, but needs a 9V supply to drive the display. Here&#8217;s a photo of the screen mounted on the evaluation board:</p>
<div id="attachment_55" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.gauravmanek.com/blog/wp-content/uploads/2011/11/DSC_6502.jpg"><img class="size-medium wp-image-55" title="Densitron DD-6448BE-2A" src="http://www.gauravmanek.com/blog/wp-content/uploads/2011/11/DSC_6502-300x200.jpg" alt="" width="300" height="200" /></a><p class="wp-caption-text">Densitron DD-6448BE-2A</p></div>
<p>And here&#8217;s a closer view of the screen itself; It&#8217;s only 18.5 mm wide and 18.1 mm tall:</p>
<div id="attachment_56" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.gauravmanek.com/blog/wp-content/uploads/2011/11/DSC_6503.jpg"><img class="size-medium wp-image-56" title="Closer Look" src="http://www.gauravmanek.com/blog/wp-content/uploads/2011/11/DSC_6503-300x200.jpg" alt="" width="300" height="200" /></a><p class="wp-caption-text">Closer Look</p></div>
<p>More details (and the review proper) in a few weeks&#8217; time!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gauravmanek.com/blog/?feed=rss2&#038;p=53</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Persistence of Vision prototype</title>
		<link>http://www.gauravmanek.com/blog/?p=42</link>
		<comments>http://www.gauravmanek.com/blog/?p=42#comments</comments>
		<pubDate>Sun, 26 Jun 2011 07:23:10 +0000</pubDate>
		<dc:creator>gauravmm</dc:creator>
				<category><![CDATA[Projects]]></category>
		<category><![CDATA[cs]]></category>
		<category><![CDATA[research]]></category>
		<category><![CDATA[technical]]></category>

		<guid isPermaLink="false">http://www.gauravmanek.com/blog/?p=42</guid>
		<description><![CDATA[Recently, I saw an impressive business card how-to that uses Persistence of Vision to display floating text. Take a look at it. I was considering the plausibility of a version of this card that can display the text and graphics in color. The basic mechanism (Persistence of Vision) is still the same, but the new [...]]]></description>
			<content:encoded><![CDATA[<p>Recently, I saw an impressive business card how-to that uses Persistence of Vision to display floating text. <a href="http://www.instructables.com/id/Circuit-Board-Lab-POV-Business-Card/">Take a look at it</a>.</p>
<p>I was considering the plausibility of a version of this card that can display the text and graphics in color. The basic mechanism (Persistence of Vision) is still the same, but the new card uses either 3-color RGB SMD LEDs (which are prohibitively expensive), or three rows of LEDs (red, green and blue each get their own row).</p>
<p style="text-align: center;"><img class="aligncenter size-full wp-image-44" title="Normal PoV Card" src="http://www.gauravmanek.com/blog/wp-content/uploads/2011/06/single_LED_row.png" alt="" width="540" height="400" /></p>
<p><strong>Row Alignment</strong></p>
<p>In a normal PoV card, the text is displayed along a single arc (the yellow path). Once multiple rows of LEDs are introduced, it becomes necessary to align them such that all their paths coincide in order to display a single color image. Without any alignment, there is an obvious separation in the paths. In the diagram below, observe how the paths appear to coincide closest to the vertical position, but are far apart at the ends:</p>
<p style="text-align: center;"><img class="size-full wp-image-46 aligncenter" title="3_LED_row_unaligned" src="http://www.gauravmanek.com/blog/wp-content/uploads/2011/06/3_LED_row_unaligned.png" alt="" width="540" height="400" /></p>
<p>For the rows to be successfully aligned, they must converge at the point of the elbow (assuming, of course, that the person holding the card holds his elbow in a fixed position while viewing these cards). The alignment must be like this:</p>
<p style="text-align: center;"><img class="aligncenter size-full wp-image-47" title="3_LED_row_fixed_alignment" src="http://www.gauravmanek.com/blog/wp-content/uploads/2011/06/3_LED_row_fixed_alignment.png" alt="" width="540" height="400" /></p>
<p>Where <em>r</em> is the distance from the pivot point (your elbow) to the lowest LED, and <em>θ</em> is the angular displacement between two adjacent rows. Notice that the arcs do overlap, but have an angular displacement. This is unavoidable, and can be (reasonably) easily corrected in software. The exact method used to correct this is discussed in the next section. In the final model, it is desirable to make <em>θ </em>as small as possible<em>. </em>Also, you must know the value of <em>r</em> before you can build the card.</p>
<p style="text-align: center;"><img class="aligncenter size-full wp-image-48" title="3_LED_row_fixed_alignment_card" src="http://www.gauravmanek.com/blog/wp-content/uploads/2011/06/3_LED_row_fixed_alignment_card.png" alt="" width="540" height="400" /></p>
<p>Calculate the exact placement of each of the LEDs in such an arrangement only requires basic trigonometry (or even geometry), and is left as <a href="http://uncyclopedia.wikia.com/wiki/Proof#Proof_by_Omission" target="_blank">an exercise to the reader</a>. The main constraining variables are <em>r</em>, <em>d</em>, and the minimum distance between LEDs. Assuming 0.5m (a child&#8217;s arm), 5 cm and 8 mm (respectively), <em>θ</em> = 0.9° and the topmost LEDs will be 9 mm apart &#8211; a close-to-parallel construction. In fact, using the above values for <em>d</em> and minimum distance, we can quickly plot the difference in spacing (in mm) against the arm length (in meters):</p>
<div id="attachment_49" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.gauravmanek.com/blog/wp-content/uploads/2011/06/graph.png"><img class="size-medium wp-image-49 " title="graph" src="http://www.gauravmanek.com/blog/wp-content/uploads/2011/06/graph-300x188.png" alt="" width="300" height="188" /></a><p class="wp-caption-text">Displacement against r</p></div>
<p>It&#8217;s possible to make a card with moving sections that allow a person to pick their height, but that would simply be overkill. Here&#8217;s a design:</p>
<p style="text-align: center;"><img class="aligncenter size-full wp-image-50" title="3_LED_row_movable" src="http://www.gauravmanek.com/blog/wp-content/uploads/2011/06/3_LED_row_movable.png" alt="" width="540" height="400" /></p>
<p>If you implement, do tell me! The combination of precise cutting and moving electronics puts this out of the reach of all but the most determined hobbyists.</p>
<p>I have an initial prototype of a single-color device, made using cardboard, copper tape and an Arduino Uno (not mounted on the card itself &#8211; for obvious reasons). This is the card with two LEDs lit:</p>
<div id="attachment_51" class="wp-caption aligncenter" style="width: 210px"><a href="http://www.gauravmanek.com/blog/wp-content/uploads/2011/06/DSC_5184.jpg"><img src="http://www.gauravmanek.com/blog/wp-content/uploads/2011/06/DSC_5184-200x300.jpg" alt="" title="DSC_5184" width="200" height="300" class="size-medium wp-image-51" /></a><p class="wp-caption-text">Prototype</p></div>
<p>And this is the circuit diagram sketched out on the cardboard, with components placed appropriately:</p>
<div id="attachment_52" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.gauravmanek.com/blog/wp-content/uploads/2011/06/DSC_5180.jpg"><img src="http://www.gauravmanek.com/blog/wp-content/uploads/2011/06/DSC_5180-300x200.jpg" alt="" title="DSC_5180" width="300" height="200" class="size-medium wp-image-52" /></a><p class="wp-caption-text">Sketch</p></div>
]]></content:encoded>
			<wfw:commentRss>http://www.gauravmanek.com/blog/?feed=rss2&#038;p=42</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>iPad- and Kinect-Controlled Car</title>
		<link>http://www.gauravmanek.com/blog/?p=33</link>
		<comments>http://www.gauravmanek.com/blog/?p=33#comments</comments>
		<pubDate>Mon, 28 Mar 2011 13:23:44 +0000</pubDate>
		<dc:creator>gauravmm</dc:creator>
				<category><![CDATA[Projects]]></category>
		<category><![CDATA[arduino]]></category>
		<category><![CDATA[cs]]></category>
		<category><![CDATA[kinect]]></category>
		<category><![CDATA[research]]></category>
		<category><![CDATA[technical]]></category>
		<category><![CDATA[web development]]></category>

		<guid isPermaLink="false">http://www.gauravmanek.com/blog/?p=33</guid>
		<description><![CDATA[This project extends a simple remote-controlled car, allowing it to be controlled by an iPad or by hand gestures. This project builds on the Arduino project, the Kinect and certain HTML5 features (WebSockets, DeviceMotionEvent, Canvas). The final product is this: Overview There are two different versions of this project &#8211; one for the HTML5 web [...]]]></description>
			<content:encoded><![CDATA[<p>This project extends a simple remote-controlled car, allowing it to be controlled by an iPad or by hand gestures. This project builds on the <a href="http://arduino.cc/" target="_blank">Arduino</a> project, the Kinect and certain HTML5 features (<a href="http://en.wikipedia.org/wiki/WebSockets" target="_blank">WebSockets</a>, <a href="http://developer.apple.com/library/safari/#documentation/SafariDOMAdditions/Reference/DeviceMotionEventClassRef/DeviceMotionEvent/DeviceMotionEvent.html#//apple_ref/javascript/cl/DeviceMotionEvent" target="_blank">DeviceMotionEvent</a>, <a href="http://en.wikipedia.org/wiki/Canvas_element">Canvas</a>). The final product is this:</p>
<p><object width="640" height="390"><param name="movie" value="http://www.youtube.com/v/D7Ses-VGU9U&amp;hl=en_US&amp;feature=player_embedded&amp;version=3" /><param name="allowFullScreen" value="true" /><param name="allowScriptAccess" value="always" /><embed type="application/x-shockwave-flash" width="640" height="390" src="http://www.youtube.com/v/D7Ses-VGU9U&amp;hl=en_US&amp;feature=player_embedded&amp;version=3" allowfullscreen="true" allowscriptaccess="always"></embed></object></p>
<p><strong>Overview</strong></p>
<p>There are two different versions of this project &#8211; one for the HTML5 web app, and the other for the Kinect. In the HTML5-based version, the web application uses <a href="http://developer.apple.com/library/safari/#documentation/SafariDOMAdditions/Reference/DeviceMotionEventClassRef/DeviceMotionEvent/DeviceMotionEvent.html#//apple_ref/javascript/cl/DeviceMotionEvent" target="_blank">DeviceMotionEvent</a> to get accelerometer readings and determine what the car has to do. This action is encoded in the format expected by the Arduino sketch, and is then sent over a <a href="http://en.wikipedia.org/wiki/WebSockets" target="_blank">WebSocket</a> to a simple server written in Python. The Python script simply forwards the received data to the Arduino via the serial port. The Arduino toggles its output to close and open switches on the remote controller (using optical isolators). The car moves correspondingly.</p>
<p>The Kinect-based version functions in a nearly identical manner &#8211; the only difference is that the Kinect data is received and processed in the same C# application that dispatches instructions over the serial port. You can <a title="Download Source Code!" href="http://www.gauravmanek.com/blog/wp-content/uploads/2011/03/RC_Car.zip" target="_blank">download the full source code here</a>.</p>
<p>Now, to take a closer look at each section of this project, from the bottom-up:</p>
<p><strong>The Arduino</strong></p>
<p>The Arduino receives commands from its Serial interface and toggles its output to control the car&#8217;s remote controller.  For a controller that supports only one speed, the circuit looks like this:</p>
<div id="attachment_35" class="wp-caption aligncenter" style="width: 281px"><a href="http://www.gauravmanek.com/blog/wp-content/uploads/2011/03/RC-Control_bb.png"><img class="size-medium wp-image-35" title="Circuit" src="http://www.gauravmanek.com/blog/wp-content/uploads/2011/03/RC-Control_bb-271x300.png" alt="" width="271" height="300" /></a><p class="wp-caption-text">Fritzing image of circuit.</p></div>
<p>Each output pin controls current passing through an <a href="http://en.wikipedia.org/wiki/Opto-isolator" target="_blank">opto-isolator</a>, which isolates the circuit of the Arduino from that of the car&#8217;s controller. This allows the Arduino to control the car, despite both circuits having different electrical potentials. The switches at the top of the above diagrams are placeholders for the actual control mechanism of the car.  A current-limiting resistor is chosen so as to provide a current within the operating parameters of the opto-isolator. The breadboarded circuit looks like this:</p>
<div id="attachment_36" class="wp-caption aligncenter" style="width: 253px"><a href="http://www.gauravmanek.com/blog/wp-content/uploads/2011/03/DSC_5087.jpg"><img class="size-medium wp-image-36" title="RC Car - Photo of Circuit" src="http://www.gauravmanek.com/blog/wp-content/uploads/2011/03/DSC_5087-243x300.jpg" alt="" width="243" height="300" /></a><p class="wp-caption-text">Photo of Arduino Circuit</p></div>
<p>The sketch that the Arduino runs is very simple:</p>
<pre class="brush: cpp; title: ; notranslate">int pinRight = 11;
int pinLeft = 10;
int pinForward = 9;
int pinReverse = 8;

void setup() {
  Serial.begin(9600);
  pinMode(pinRight, OUTPUT);
  pinMode(pinLeft, OUTPUT);
  pinMode(pinForward, OUTPUT);
  pinMode(pinReverse, OUTPUT);
}

void loop() {
  if(Serial.available() &gt; 0){
    int tmpByte = Serial.read();
    switch(tmpByte){
      case 'w': // Move car FORWARDS
        digitalWrite(pinReverse, LOW);
        digitalWrite(pinForward, HIGH);
        break;
      case 's': // Move car in REVERSE
        digitalWrite(pinForward, LOW);
        digitalWrite(pinReverse, HIGH);
        break;
      case 'a': // Turn steering wheels LEFT
        digitalWrite(pinRight, LOW);
        digitalWrite(pinLeft, HIGH);
        break;
      case 'd': // Turn steering wheels RIGHT
        digitalWrite(pinLeft, LOW);
        digitalWrite(pinRight, HIGH);
        break;
      case '_': // STOP ALL motion
        digitalWrite(pinReverse, LOW);
        digitalWrite(pinForward, LOW);
        // The missing break; here is entirely intentional.
      case 'x': // Move steering wheels STRAIGHT
        digitalWrite(pinRight, LOW);
        digitalWrite(pinLeft, LOW);
        break;
      default:
        break;
    }
  }
}
</pre>
<p>Notice that the <code>digitalWrite(pin, LOW);</code> always precedes the <code>digitalWrite(pin, HIGH);</code> command? This is to prevent conflicting commands from being sent to the car(e.g. Forwards and Backwards simultaneously).</p>
<p>And now, on to the Web App-based controller:</p>
<p><strong>Web Application Controller</strong></p>
<p>This controller comes in two parts. One is the actual client, which is served as a single html file (with optional additions &#8211; discussed later), and one is the server, which is a Python script that simply copies all data sent over a WebSocket to the Arduino over a serial port. This is how the client interface looks like:</p>
<div id="attachment_37" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.gauravmanek.com/blog/wp-content/uploads/2011/03/Untitled-1.png"><img class="size-medium wp-image-37" title="iPad Interface" src="http://www.gauravmanek.com/blog/wp-content/uploads/2011/03/Untitled-1-300x199.png" alt="The web app on an iPad." width="300" height="199" /></a><p class="wp-caption-text">The web app on an iPad.</p></div>
<p>The server is based on <a href="http://pastebin.com/zBjN02jQ" target="_blank">this</a> Python script (if you want to use a test server, grab <a href="http://pastebin.com/d8SDbbED" target="_blank">this</a> code &#8211; the response headers adhere to the Same-Origin Policy). <a href="http://sourceforge.net/projects/pyserial/files/pyserial/2.5/" target="_blank">pyserial</a> 2.5 is used to send output to the Arduino.</p>
<p>The web-based client, on the other hand, is much more complex and interesting. A single file (index.html) draws the GUI (using Canvas), reads the tilt angle of the device (using DeviceMotionEvent), calculates the action that the car has to perform and sends the action to the Python script over a WebSocket connection. HTML5 is certainly useful, isn&#8217;t it?</p>
<p>The JavaScript has been extensively commented, and is included (along with the optional files) in the download above.</p>
<p>The purpose of the optional files (<code>cache_manifest.php</code> and <code>date.php</code>) is explained <a title="iPad Web App – Cache Manifests" href="http://www.gauravmanek.com/blog/?p=31" target="_blank">here</a>. They are not essential to the functioning of the code.</p>
<p><strong>Kinect Controller</strong></p>
<p>The Kinect controller is written using <a href="http://codelaboratories.com/nui/" target="_blank">Code Laboratories&#8217; CL NUI SDK</a> instead of the more commonly used (and official) OpenNI or OpenKinect/libfreenect. The primary motivation in choosing CL NUI over the other SDKs is that CL NUI makes writing code in C# very easy and serial communication is a trivially easy in C#. The tradeoff of writing in managed C# is that (1) Threading is inevitable, which adds to the complexity of the code and (2) The image processing code runs painfully slowly. The software looks like this:</p>
<div id="attachment_38" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.gauravmanek.com/blog/wp-content/uploads/2011/03/screenshot_kinect.png"><img class="size-medium wp-image-38" title="screenshot_kinect" src="http://www.gauravmanek.com/blog/wp-content/uploads/2011/03/screenshot_kinect-300x180.png" alt="" width="300" height="180" /></a><p class="wp-caption-text">Kinect view.</p></div>
<p>The bar on the left is not relevant to this project &#8211; it is just a quick way to move the Kinect up and down (using the built-in motor) and to read and graph the angle over time. The algorithm used to detect the position of the hand has been deliberately kept simple &#8211; working with System.Drawing.Bitmap objects is very slow. Here is the algorithm:</p>
<pre class="brush: cpp; title: ; notranslate">
// System.Drawing.Bitmap bmpVideoData contains the current frame.
// double xbar, ybar contain the running average of the points that lie
// 	in the desired depth range. Tweak the incremented values until satisfied
// 	with the accuracy and speed trade-off. The choice of 10 is arbitrary.
for(int i=0; i&lt;bmpVideoData.Width; i+=10)
    for(int j=0; j&lt;bmpVideoData.Height; j+=10){
        c = bmpVideoData.GetPixel(i, j);
        // Check to see if color of pixel in depth map corresponds to the desired
        // depth range. This was manually calculated beforehand, but can be
        // automated if the range needs to be varied.
        if (c.R == 0 &amp;&amp; c.B == 255 &amp;&amp; c.G &lt; 192) {
            // Live, numerically stable, mean calculation:
            ++count;
            xbar += (i - xbar) / count; // Update the mean x value
            ybar += (j - ybar) / count; // Update the mean y value
        }
    }
// xbar and ybar will be used to calculate the position of the hand onscreen,
// and the action to be performed by the robot.
</pre>
<p>&nbsp;</p>
<p>As algorithms go, this is among the simplest. It gives surprisingly robust tracking, though. Do note that you need to install <a href="http://codelaboratories.com/nui/" target="_blank">Code Laboratories&#8217; CL NUI SDK</a> before you can run the code included in the download above. Once you have done that, copy <code>CLNUIDevice.cs</code>,  <code>CLNUIDevice.dll</code> and  <code>NUIImage.cs</code> into the project folder, replacing the existing files. (As per their SDK license requirements, I cannot distribute these files directly).</p>
<p><strong>Future Expansion</strong></p>
<ol>
<li>Use the Ethernet shield and write a sketch that allows the Arduino to act as a WebSocket server. This will remove the need for having a computer as an intermediary (to forward WebSocket data to the Arduino over the serial port).</li>
<li>Modify the web app code to automatically use the internal gyroscope when available (by using <a href="http://dev.w3.org/geo/api/spec-source-orientation" target="_blank">DeviceOrientationEvent</a> instead of DeviceMotionEvent). When I eventually get a device with a gyroscope, I&#8217;ll look into it.</li>
<li>Implement the same thing in a toy helicopter. Same concept, new dimension! Use the Kinect to gather positional data, and the iPad to steer it around.</li>
<li>Modify the vision algorithm to detect each hand separately (using a conditional floodfill), and allow each hand to control a different car. Alternatively, use it to steer a helicopter in three dimensions.</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://www.gauravmanek.com/blog/?feed=rss2&#038;p=33</wfw:commentRss>
		<slash:comments>54</slash:comments>
		</item>
		<item>
		<title>iPad Web App &#8211; Cache Manifests</title>
		<link>http://www.gauravmanek.com/blog/?p=31</link>
		<comments>http://www.gauravmanek.com/blog/?p=31#comments</comments>
		<pubDate>Thu, 17 Feb 2011 13:07:57 +0000</pubDate>
		<dc:creator>gauravmm</dc:creator>
				<category><![CDATA[Projects]]></category>
		<category><![CDATA[cs]]></category>
		<category><![CDATA[technical]]></category>
		<category><![CDATA[web development]]></category>

		<guid isPermaLink="false">http://www.gauravmanek.com/blog/?p=31</guid>
		<description><![CDATA[Recently, the Minesweeper3D project was adapted into a web application for iPad &#8211; complete with multi-touch gestures and offline caching. It&#8217;s available here, with the source code here. iPad web application can be written to function remarkably like native applications. With the ability to keep a copy of the web app for offline use, web [...]]]></description>
			<content:encoded><![CDATA[<p>Recently, the Minesweeper3D project was adapted into a web application for iPad &#8211; complete with multi-touch gestures and offline caching. It&#8217;s available <a href="http://www.gauravmanek.com/projects/3dminesweeper/iPad/index_iPad.html" target="_blank">here</a>, with the source code <a href="http://www.gauravmanek.com/projects/3dminesweeper/iPad/" target="_blank">here</a>.</p>
<p>iPad web application can be written to function remarkably like native applications. With the ability to keep a copy of the web app for offline use, web apps are made a lot more useful. Cache manifests are used to make this happen on iOS (see the official document <a href="http://www.w3.org/TR/html5/offline.html" target="_blank">here</a>).</p>
<p>A cache manifest is simply a list of all the files required by the app to run offline. It must be served with the Content-Type header set to text/cache-manifest and the first line must be</p>
<p>CACHE MANIFEST</p>
<p>. Each relative file path must occur on a separate line, and all text after a # is ignored. Files are updated when the hash of the manifest file changes. A sample manifest file is here:</p>
<pre class="brush: plain; highlight: [1]; title: ; notranslate">
CACHE MANIFEST
# Sample Manifest
index.html
arbitrary.js
</pre>
<p>For the Minesweeper3D project, the cache manifest is generated by a simple script. Feel free to modify it for your own use:</p>
<pre class="brush: php; title: ; notranslate">
&lt;?php
$files = array(&quot;index_iPad.html&quot;, &quot;display_canvas_iPad.js&quot;, &quot;date.php&quot;, ... );
header(&quot;Content-Type: text/cache-manifest&quot;);
?&gt;
CACHE MANIFEST
# Manifest for Minesweeper3D
# Uses filemtime() to automatically change contents
&lt;?php
foreach ($files as $fn)
	echo $fn.&quot;\n# Mod:&quot;.filemtime($fn).&quot;\n\n&quot;;
?&gt;
</pre>
<p>Since the hash of the manifest file is used to determine if the files need to be redownloaded, even changing the contents of the comments will cause the browser to download the files again. The above script takes advantage of that by including the time that each file was last modified as a comment &#8211; any change in the contents of a file will cause the timestamp to change, which will change the hash of the manifest. As the manifest is downloaded each time the application is open, this simple method may prove to be too resource intensive. This can easily addressed by caching the cache file &#8211; an amusingly self-referential but effective method.</p>
<p><strong>Version tracking</strong></p>
<p>Debugging the cache system is usually difficult, but here is a simple way to keep track of the current version present in the cache. This solution comes in two parts, and is compatible with the above manifest making script. It comes as an external php script that is just two lines long:</p>
<pre class="brush: php; title: ; notranslate">
&lt;?php
header(&quot;Content-type: application/x-javascript&quot;);
echo &quot;var php_date=\&quot;&quot;.date(&quot;r&quot;).&quot;\&quot;;&quot;;
?&gt;
</pre>
<p>It acts as an external JavaScript file that defines the value of the variable php_date to be the date and time that the file was accessed. Since the client only updates the files when the manifest changes, the cache version of this file <em>will not change until the manifest changes</em>. Hence, the date stored in this file is the date at which the file was last downloaded.</p>
<pre class="brush: jscript; title: ; notranslate">
function display_initialize(){
	// ...
	document.getElementById(&quot;update_date&quot;).innerHTML = php_date;
}
</pre>
<p>Adding a single line to display this date allows us to keep track of the version that is currently being used to display the document. Simple and effective.</p>
<p>A few things to note:</p>
<p>Using the manifest file overrides any other cache directive &#8211; HTTP headers, browser configuration, etc. Even pages served over HTTPS are not exempt from this behavior.</p>
<p>The web app can only directly include files mentioned in the manifest. For example, using a &lt;script&gt; tag to include <em>arbitrary.js</em> will only succeed if the manifest file also mentions <em>arbitrary.js</em>. If the file is not mentioned, then it will not be available in the app. Changing this default behavior can be done by appending this to the end of the cache manifest:</p>
<pre class="brush: plain; first-line: 5; title: ; notranslate">
NETWORK:
*
</pre>
<p><strong>Canvas Rendering</strong></p>
<p>Interestingly enough, the canvas rendering is not hardware accelerated. To prevent visible latency in the animations, the variable ani_ActiveMovement in display_canvas_iPad.js disables the rendering of text in the main grid as animation. Uncommenting line 13 from the snippet below enables that &#8220;feature&#8221;. (Ultimately, the problem of lag was solved by changing the frame rate and increasing the &#8220;snap&#8221; distance.)</p>
<pre class="brush: jscript; highlight: [5,13]; title: ; notranslate">
function ani_moveToTargetZ(tgtZ){
	if(isNaN(tgtZ)) return;
	if(Math.abs(current_z-tgtZ) &amp;lt; 0.1){
		current_z = tgtZ;
		ani_ActiveMovement = false;
		display_Z_slice(current_z);
		return;
	}
	current_z = (current_z + tgtZ)/2;
	display_Z_slice(current_z);
	// Check timer
	clearTimeout(ani_timer1);
	//ani_ActiveMovement=true;
	ani_timer1 = setTimeout(&quot;ani_moveToTargetZ(&quot; + tgtZ + &quot;)&quot;, 40);
}
</pre>
<p>Hopefully, hardware rendering will be enabled in a future update.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gauravmanek.com/blog/?feed=rss2&#038;p=31</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>The story of Blinky, Inky, Pinky and Clyde.</title>
		<link>http://www.gauravmanek.com/blog/?p=26</link>
		<comments>http://www.gauravmanek.com/blog/?p=26#comments</comments>
		<pubDate>Fri, 04 Feb 2011 18:31:44 +0000</pubDate>
		<dc:creator>gauravmm</dc:creator>
				<category><![CDATA[Projects]]></category>
		<category><![CDATA[cs]]></category>
		<category><![CDATA[meta]]></category>
		<category><![CDATA[technical]]></category>
		<category><![CDATA[web development]]></category>

		<guid isPermaLink="false">http://www.gauravmanek.com/blog/?p=26</guid>
		<description><![CDATA[All modern browsers limit the number of concurrent connections that they establish with HTTP servers so that connections and devices are not overburdened. There are usually two limits: a cap on the number of connections to a host, and another cap on the total number of outbound connections. At the time the HTTP/1.1 standard was [...]]]></description>
			<content:encoded><![CDATA[<p>All modern browsers limit the number of concurrent connections that they establish with HTTP servers so that connections and devices are not overburdened. There are usually two limits: a cap on the number of connections to a host, and another cap on the total number of outbound connections. At the time the HTTP/1.1 standard was written in 1997, the limit was two connections per host (see <a href="http://tools.ietf.org/html/rfc2068#section-8.1.4" target="_blank">RFC 2068, section 8.1.4</a>). For a website that makes extensive use of included content, this limit is rather restrictive. Unsurprisingly, most modern browsers deliberately set their limits high &#8211; typically 4-6 connections per host (more <a href="http://stackoverflow.com/questions/985431/max-parallel-http-connections-in-a-browser">here</a>).</p>
<p>This problem came up when I was working on my <a href="http://www.gauravmanek.com/?tshirts" target="_blank">T-Shirt Design browser</a> &#8211; the thumbnail images were loading unbearably slowly. The limited number of connections available were forcing the thumbnails to be downloaded sequentially, rather than concurrently. This post details a rather simple way to get around this problem by using multiple hosts to serve files.</p>
<p>Maintaining mirror hosts is, with some amount of planning, rather easy &#8211; just add additional DNS A records and configure your server to serve the exact same set of files for calls to multiple domains (on Apache, just specify the same DocumentRoot for multiple <a href="http://httpd.apache.org/docs/2.0/vhosts/examples.html" target="_blank">VirtualHosts</a>). This is where the rather cryptic title of this post comes in &#8211; blinky, inky, pinky and clyde are all sub-domains of gauravmanek.com. Here is an excerpt from the DNS records of gauravmanek.com:</p>
<pre class="brush: plain; title: ; notranslate">
DNS Zone: gauravmanek.com

Record    Type    Value
------    ----    -----
           A     173.236.181.179
blinky     A     173.236.181.179
clyde      A     173.236.181.179
inky       A     173.236.181.179
pinky      A     173.236.181.179
</pre>
<p>As you can see, blinky.gauravmanek.com, inky.gauravmanek.com, pinky.gauravmanek.com, clyde.gauravmanek.com and gauravmanek.com are all on the same IP. Do note that I did not use a wildcard record for this, even though its technically possible. I don&#8217;t directly edit my httpd.conf settings, but the entries needed to generate the desired behavior should (might? possibly? I&#8217;m not particularly experienced with Apache, so don&#8217;t take my word as the gospel truth) look something like this:</p>
<pre class="brush: plain; title: ; notranslate">
NameVirtualHost *:80

&lt;VirtualHost *:80&gt;
   DocumentRoot /www/main_site
   ServerName gauravmanek.com
&lt;/VirtualHost&gt;
&lt;VirtualHost *:80&gt;
   DocumentRoot /www/main_site
   ServerName blinky.gauravmanek.com
&lt;/VirtualHost&gt;

# Repeat for inky, pinky and clyde.
</pre>
<p>Now the exact same website is being served on each of the subdomains &#8211; this means that the path to each file is the same, making our job much easier. This can be verified manually by accessing the same file via each hostname. For example:</p>
<pre class="brush: plain; title: ; notranslate">http://www.gauravmanek.com/images/OAS.gif

http://www.blinky.gauravmanek.com/images/OAS.gif

http://www.inky.gauravmanek.com/images/OAS.gif

http://www.pinky.gauravmanek.com/images/OAS.gif

http://www.clyde.gauravmanek.com/images/OAS.gif</pre>
<p>Now that the mirroring works, we can modify the client-side code/markup to spread the load across each host to meet the aim of maximizing parallel downloads. There is an important constraint to keep in mind &#8211; the browser must access a particular resource from the same host each time, or the benefits of having multiple hosts are lost (Each resource is cached by hostname, and so accessing it from another hostname will result in multiple instances of the same resource in cache. This is not good.) For static content, simply replacing each reference to a particular  file will suffice. It&#8217;s not particularly exciting, but it does work. Alternatively, a small piece of JavaScript could change the src and href attributes at runtime, but this is <a href="http://developer.yahoo.com/performance/rules.html#javascript" target="_blank">likely to worsen performance</a> (the linked article provides many of the rules that this article both builds on and breaks).</p>
<p>For dynamic content meant to be asynchronously loaded, though, this is easily implemented. Most, if not all, scripts that dynamically download resources after the page has loaded do so from an array or similar source. To load the content, simply use the iterator variable modulo number of hosts available to quickly distribute the requests into appropriate groups. As used in the (as of February 2011) current version of the T-Shirt Design Browser:</p>
<pre class="brush: jscript; title: ; notranslate">
var ts_mirrorServers = new Array(&quot;http://www.inky.gauravmanek.com&quot;, &quot;http://www.pinky.gauravmanek.com&quot;, ... , &quot;.&quot;);
// Some code
initialize() {
	for( /* each preview icon */)
		tsIcoNodes[i].src = ts_mirrorServers[i%ts_mirrorServers.length] + ts_icoPrefix + ts_icoNameArr[i];
}
</pre>
<p>And that&#8217;s it. It should work properly now.</p>
<p>There are better methods to deal with this problem (see <a href="http://spriteme.org/faq.php#def" target="_blank">SpriteMe</a>, more on this later), none are as easy to implement for dynamic content as the solution discussed on this page. (Note: I&#8217;m working on mixing sprite generation and this together. Let&#8217;s see if it works.)</p>
<p>This has one additional benefit, especially important for cookie-heavy sites. As the hosts are different, cookies that would be sent as part of the browser&#8217;s GET request are no longer sent, reducing both transfer and computational overhead. This is the reason that sites often use a single subdomain to serve static content (e.g.: static.bbc.co.uk).</p>
<p><strong>Potential Problems</strong><br />
This method is, however, rather problematic at times. There are two main overheads that are incurred that makes this unsuitable for serving many tiny files.</p>
<p>Firstly, the DNS overhead. DNS round-trips can take more than a second to complete, and absolutely no content can be transferred until this request is completed. If the mirror system is only used for a few pages (as it is in this case), then small snippets of JavaScript can be used to asynchronously download dummy images from these hosts while on other pages of the site &#8211; thereby forcing the browser to resolve the domain names beforehand. (This is scheduled for implementation, I will post an update when its done.) </p>
<p>Establishing a TCP connection is time-consuming, and this is the second overhead that makes the current method impractical. While its possible for the connection to be &#8220;reused&#8221; (using <a href="http://www.io.com/~maus/HttpKeepAlive.html" target="_blank">Connection: Keep-Alive</a>), it&#8217;s not something that can be relied upon. This is why sprites are a popular solution to this problem.</p>
<p><strong>A little more</strong></p>
<p>You might find it desirable to block access to your website on each of your mirror domains &#8211; to not do so would allow people to maintain multiple sessions on your website (if you use cookies to track sessions) and could potentially confuse people. A simple mod_rewrite directive can solve this problem. Alternatively, if you use a PHP-based CMS, put this in the head of your page:</p>
<pre class="brush: php; title: ; notranslate">
&lt;?php
if($_SERVER['HTTP_HOST'] != &quot;www.example.com&quot; &amp;&amp; $_SERVER['HTTP_HOST'] != &quot;example.com&quot;)
	if(preg_match('/^(www\.)?(blinky.|inky.|pinky.|clyde.)example\.com$/', $_SERVER['HTTP_HOST'])){
		header(&quot;Location: http://www.example.com/&quot;,TRUE,301);
		die();
	}
?&gt;
</pre>
<p>I now leave you with one final image, based on artwork from the original Pac-Man:</p>
<p><a href="http://www.gauravmanek.com/blog/wp-content/uploads/2011/02/inkyblinkypinkyclyde.png"><img class="aligncenter size-full wp-image-30" title="inkyblinkypinkyclyde" src="http://www.gauravmanek.com/blog/wp-content/uploads/2011/02/inkyblinkypinkyclyde.png" alt="" width="650" height="190" /></a></p>
<p>Perhaps I&#8217;ll put it on a t-shirt?</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gauravmanek.com/blog/?feed=rss2&#038;p=26</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>3D Histogram</title>
		<link>http://www.gauravmanek.com/blog/?p=21</link>
		<comments>http://www.gauravmanek.com/blog/?p=21#comments</comments>
		<pubDate>Mon, 31 Jan 2011 07:57:56 +0000</pubDate>
		<dc:creator>gauravmm</dc:creator>
				<category><![CDATA[Projects]]></category>
		<category><![CDATA[cs]]></category>
		<category><![CDATA[maths]]></category>
		<category><![CDATA[research]]></category>
		<category><![CDATA[technical]]></category>

		<guid isPermaLink="false">http://www.gauravmanek.com/blog/?p=21</guid>
		<description><![CDATA[Recently, as part of my research, I implemented a modified version of the algorithm detailed in this paper. While it was unsuitable for the intended purpose, the process did yield interesting results in the form of three-dimensional color-frequency histograms. First, a quick introduction to the concept of a color space: Colors are usually described, additively [...]]]></description>
			<content:encoded><![CDATA[<p>Recently, as part of my research, I implemented a modified version of the algorithm detailed in <a href="http://lagis-vi.univ-lille1.fr/bibtex/upload/2004/busin_icip_2004.pdf" target="_blank">this</a> paper. While it was unsuitable for the intended purpose, the process did yield interesting results in the form of three-dimensional color-frequency histograms.</p>
<p>First, a quick introduction to the concept of a color space: Colors are usually described, additively (starting from black and <em>adding</em> light) or subtractively (starting from white and <em>subtracting</em> light). The former is usually used with screens and computer displays (which work by adding light), and the latter with print materials (which work by adding pigments, which subtract light). By no means does this depict every possible color, but it does an excellent job in specifying colors for use by digital devices. The RGB color space is the most commonly used color space in digital images, simply because its use makes it very easy for displays to directly use, and for printers (or other devices) to convert to the appropriate format.</p>
<p>RGB is usually specified by a set of three numbers (each representing the intensity of red, green or blue present in the final mix, as an integer from 0-255 or a fraction from 0-1). Since these three colors are assumed orthogonal in human perception, they can be drawn in a cube, with each color varying along one dimension of the cube. This means that each point in the cube can be described using a unique set of three numbers, and that each set of three intensities describes a particular, unique, color. <a href="http://commons.wikimedia.org/wiki/File:RGB_Cube_Show_lowgamma_cutout_a.png" target="_blank">The image below</a> expresses this concept visually:</p>
<div id="attachment_24" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.gauravmanek.com/blog/wp-content/uploads/2011/01/RGB_Cube_Show_lowgamma_cutout_a.png"><img class="size-medium wp-image-24" title="RGB Cube" src="http://www.gauravmanek.com/blog/wp-content/uploads/2011/01/RGB_Cube_Show_lowgamma_cutout_a-300x250.png" alt="" width="300" height="250" /></a><p class="wp-caption-text">Three-dimensional visualization of the RGB colorspace. Image courtesy of SharkD on Wikimedia Commons.</p></div>
<p>The purpose of a histogram is to calculate which colors are most popular in a very simple way. The entire RGB cube is divided into &#8220;bins&#8221; of equal size, where each bin corresponds to colors that belong to the same ranges of intensities of each primary color. The divisions in the image above divide the larger cube into 5<sup>3</sup> = 125 bins. It is important for the &#8220;size&#8221;, the range of colors that each bin encompasses, to be perceptually uniform. This is not the case in the RGB model, but we can live with the assumption for now. In the final histogram, each bin contains the total number of pixels in an image that fall within its range.</p>
<p>With all this knowledge, we can now see that a three-dimensional histogram is simply a record of the color distribution within an image, and so can be used to find out the particular color or color groups that are most common in an image. One particular image of interest is Jellyfish.jpg, from the sample pictures included in modern versions of Windows.</p>
<div id="attachment_19" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.gauravmanek.com/blog/wp-content/uploads/2011/01/Jellyfish.jpg"><img class="size-medium wp-image-19 " title="Jellyfish" src="http://www.gauravmanek.com/blog/wp-content/uploads/2011/01/Jellyfish-300x225.jpg" alt="" width="300" height="225" /></a><p class="wp-caption-text">Low resolution version of Jellyfish.jpg.</p></div>
<p>This image was processed to yield a 3D histogram as described above (but with 16<sup>3</sup> = 4096 bins) and converted into a &#8220;stacked&#8221; contour plot. Each layer in this stacked plot corresponds to moving towards the maximum intensity of red by one bin (or 1/16 of the maximum color). Within each layer, the colored lines enclose areas within the histogram that all contain more than a certain number of pixels. As in a geographical contour map, the minimum limit for each contour line increases linearly.</p>
<div id="attachment_16" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.gauravmanek.com/blog/wp-content/uploads/2011/01/Jellyfish_RGB_smoothed_1.png"><img class="size-medium wp-image-16" title="Jellyfish Histogram - Smoothed RGB" src="http://www.gauravmanek.com/blog/wp-content/uploads/2011/01/Jellyfish_RGB_smoothed_1-300x231.png" alt="" width="300" height="231" /></a><p class="wp-caption-text">Smoothed RGB Histogram of Jellyfish.jpg</p></div>
<p>It is easiest to imagine that all the slices are vertically stacked and that lines of similar colors are connected between layers. Doing so will give you a series of polygons enclosing colors that all occur at least a certain minimum number of times. For quick reference, the color of each bin can be seen here:</p>
<div id="attachment_20" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.gauravmanek.com/blog/wp-content/uploads/2011/01/RGB_Color.png"><img class="size-medium wp-image-20" title="RGB Color Lookup" src="http://www.gauravmanek.com/blog/wp-content/uploads/2011/01/RGB_Color-300x231.png" alt="" width="300" height="231" /></a><p class="wp-caption-text">Color Lookup</p></div>
<p>It is easy to manually verify that the most common maximum colors are the dark blue of the background and the orange of the jellyfish.</p>
<p>Of course, this particular histogram has been smoothed. The original histogram, as shown below, has considerably thin peaks, suggesting that colors within a group tend towards a central value rather strongly. A three dimensional Gaussian convolution matrix was applied (with σ = 1.33 bins) was applied to get the rather nice looking histogram above.</p>
<div id="attachment_15" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.gauravmanek.com/blog/wp-content/uploads/2011/01/Jellyfish_RGB_raw.png"><img class="size-medium wp-image-15" title="Jellyfish Histogram - Raw RGB" src="http://www.gauravmanek.com/blog/wp-content/uploads/2011/01/Jellyfish_RGB_raw-300x231.png" alt="" width="300" height="231" /></a><p class="wp-caption-text">Raw RGB Histogram of Jellyfish.jpg</p></div>
<p>The whole process relies heavily on a few key assumptions. Perhaps the most important assumption is that the intensity of a particular color varies linearly with the value used to express it. As far as the RGB color space is concerned, this is not true. This leads to the process being non-representative in a number of important ways:</p>
<ul>
<li>Smoothing is not representative of colors perceived.</li>
<li>Color grouping is likely to be too aggressive in colors where human eyes can differentiate shades the best and not sufficiently aggressive at other colors.</li>
</ul>
<p>If you have managed to read this far, then congratulations! Here is the same data in other color spaces.</p>
<p><strong>YCbCr</strong></p>
<p><a href="http://www.gauravmanek.com/blog/wp-content/uploads/2011/01/Jellyfish_YCbCr_smoothed.png"></a></p>
<p><div id="attachment_18" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.gauravmanek.com/blog/wp-content/uploads/2011/01/Jellyfish_YCbCr_smoothed.png"><img class="size-medium wp-image-18" title="Jellyfish Histogram - Smoothed YCbCr" src="http://www.gauravmanek.com/blog/wp-content/uploads/2011/01/Jellyfish_YCbCr_smoothed-300x211.png" alt="" width="300" height="211" /></a><p class="wp-caption-text">Jellyfish Histogram - Smoothed YCbCr</p></div><br />
<div id="attachment_17" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.gauravmanek.com/blog/wp-content/uploads/2011/01/Jellyfish_YCbCr_raw.png"><img class="size-medium wp-image-17" title="Jellyfish Histogram - Raw YCbCr" src="http://www.gauravmanek.com/blog/wp-content/uploads/2011/01/Jellyfish_YCbCr_raw-300x211.png" alt="" width="300" height="211" /></a><p class="wp-caption-text">Jellyfish Histogram - Raw YCbCr</p></div></p>
<p><strong>HSV</strong></p>
<p><div id="attachment_14" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.gauravmanek.com/blog/wp-content/uploads/2011/01/Jellyfish_HSV_smoothed.gif"><img class="size-medium wp-image-14" title="Jellyfish Histogram - Smoothed HSV" src="http://www.gauravmanek.com/blog/wp-content/uploads/2011/01/Jellyfish_HSV_smoothed-300x211.gif" alt="" width="300" height="211" /></a><p class="wp-caption-text">Jellyfish Histogram - Smoothed HSV</p></div><br />
<div id="attachment_13" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.gauravmanek.com/blog/wp-content/uploads/2011/01/Jellyfish_HSV_raw.gif"><img class="size-medium wp-image-13" title="Jellyfish Histogram - Raw HSV" src="http://www.gauravmanek.com/blog/wp-content/uploads/2011/01/Jellyfish_HSV_raw-300x211.gif" alt="" width="300" height="211" /></a><p class="wp-caption-text">Jellyfish Histogram - Raw HSV</p></div></p>
<p>Do note that the Gaussian smoothing used does not &#8220;wrap around&#8221; the hue dimension in the smoothed HSV histogram.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gauravmanek.com/blog/?feed=rss2&#038;p=21</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Fun With Lasers</title>
		<link>http://www.gauravmanek.com/blog/?p=4</link>
		<comments>http://www.gauravmanek.com/blog/?p=4#comments</comments>
		<pubDate>Thu, 27 Jan 2011 14:36:20 +0000</pubDate>
		<dc:creator>gauravmm</dc:creator>
				<category><![CDATA[Random]]></category>
		<category><![CDATA[laser]]></category>
		<category><![CDATA[photography]]></category>
		<category><![CDATA[physics]]></category>
		<category><![CDATA[random]]></category>

		<guid isPermaLink="false">http://www.gauravmanek.com/blog/?p=4</guid>
		<description><![CDATA[Last weekend, a friend and I spent some time photographing laser beams. Laser beams are not directly visible in air, and so talcum powder was used to scatter light. The first such image (of two laser beams) was generated by taking a long exposure shot in a darkened room. Talcum powder was spread by a [...]]]></description>
			<content:encoded><![CDATA[<p>Last weekend, a friend and I spent some time photographing laser beams.</p>
<p>Laser beams are not directly visible in air, and so talcum powder was used to scatter light. The first such image (of two laser beams) was generated by taking a long exposure shot in a darkened room. Talcum powder was spread by a person standing in front of the screen, and the long exposure resulted in the image of the moving person being almost completely &#8220;averaged out&#8221;.</p>
<div id="attachment_5" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.gauravmanek.com/blog/wp-content/uploads/2011/01/DSC_3951.jpg"><img class="size-medium wp-image-5 " title="Fun With Lasers - Initial Method" src="http://www.gauravmanek.com/blog/wp-content/uploads/2011/01/DSC_3951-300x200.jpg" alt="" width="300" height="200" /></a><p class="wp-caption-text">Initial Method of viewing a laser beam.</p></div>
<p>Admittedly, this particular photo has a number of salient flaws: the non-uniform background; the lack of contrast between the laser and the screen; the slight shake in the image from the pressing of the shutter release.</p>
<p>The set-up was then reworked to use a single laser device. Two mirrors were used to bounce a beam back and forth in front of the screen. The screen itself was moved towards the camera, and a ladder was placed behind the screen, allowing a person to spread talcum powder easily while not appearing in the image. The camera itself was tethered to a computer, and the shutter release was triggered over USB, eliminating camera shake.</p>
<p>Subsequent images showed substantial improvement:</p>
<div id="attachment_6" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.gauravmanek.com/blog/wp-content/uploads/2011/01/DSC_3966.jpg"><img class="size-medium wp-image-7" title="Fun With Lasers - Long Exposure" src="http://www.gauravmanek.com/blog/wp-content/uploads/2011/01/DSC_3966-300x200.jpg" alt="" width="300" height="200" /></a><p class="wp-caption-text">Long exposure shot of laser beam.</p></div>
<p>The ray from the laser source is the bottom-most one, with the source placed on the right. The lowest ray is much more well-defined than the highest one, suggesting that either the laser source is not particularly good (the beam divergence is high) or the mirrors are imperfect (either with dust on the surface or an imperfect reflective surface). The gap between lasers decreases upwards, once again due to the mirror being slightly warped.</p>
<p>The red &#8220;glow&#8221; around the laser beam is probably due to secondary scattering by talcum powder between the camera lens and the plane of the lasers. This effect was especially pronounced towards the end of this experimentation, when a large amount of powder was present in the air.</p>
<p>Compare the above image to one that has a (relatively) short exposure time:</p>
<div id="attachment_7" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.gauravmanek.com/blog/wp-content/uploads/2011/01/DSC_3965.jpg"><img class="size-medium wp-image-6" title="Fun With Lasers - Short Exposure" src="http://www.gauravmanek.com/blog/wp-content/uploads/2011/01/DSC_3965-300x200.jpg" alt="" width="300" height="200" /></a><p class="wp-caption-text">Same setup, shorter exposure.</p></div>
<p>You can see the contribution a single particle makes towards the entire image by examining the left side of the image. The glow is also substantially less intense in this image.</p>
<p>Here is a photo of the set-up with the screen removed:</p>
<div id="attachment_7" class="wp-caption aligncenter" style="width: 210px"><a href="http://www.gauravmanek.com/blog/wp-content/uploads/2011/01/DSC_4017.jpg"><img class="size-medium wp-image-9" title="Fun With Lasers - Behind the Screen" src="http://www.gauravmanek.com/blog/wp-content/uploads/2011/01/DSC_4017-200x300.jpg" alt="" width="200" height="300" /></a><p class="wp-caption-text">Behind the screen.</p></div>
<p>Notice the bottle of talcum powder?</p>
<p>Future expansion for this includes using a laser &#8220;slice&#8221; to track the flow of particles within a moving fluid.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gauravmanek.com/blog/?feed=rss2&#038;p=4</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Blog!</title>
		<link>http://www.gauravmanek.com/blog/?p=3</link>
		<comments>http://www.gauravmanek.com/blog/?p=3#comments</comments>
		<pubDate>Wed, 26 Jan 2011 14:48:57 +0000</pubDate>
		<dc:creator>gauravmm</dc:creator>
				<category><![CDATA[Meta]]></category>
		<category><![CDATA[meta]]></category>
		<category><![CDATA[web development]]></category>

		<guid isPermaLink="false">http://www.gauravmanek.com/blog/?p=3</guid>
		<description><![CDATA[The blog is finally up. The WordPress theme still requires some spit and polish, so please do bear with the rough edges.]]></description>
			<content:encoded><![CDATA[<p>The blog is finally up.<br />
The WordPress theme still requires some spit and polish, so please do bear with the rough edges.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gauravmanek.com/blog/?feed=rss2&#038;p=3</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Hello world!</title>
		<link>http://www.gauravmanek.com/blog/?p=1</link>
		<comments>http://www.gauravmanek.com/blog/?p=1#comments</comments>
		<pubDate>Sat, 22 Jan 2011 14:36:58 +0000</pubDate>
		<dc:creator>gauravmm</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.gauravmanek.com/blog/?p=1</guid>
		<description><![CDATA[Welcome to WordPress. This is your first post. Edit or delete it, then start blogging!]]></description>
			<content:encoded><![CDATA[<p>Welcome to WordPress. This is your first post. Edit or delete it, then start blogging!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gauravmanek.com/blog/?feed=rss2&#038;p=1</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

