<?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>Adrian McCarthy &#187; Projects</title>
	<atom:link href="http://www.adrianmccarthy.com/blog/?feed=rss2&#038;cat=4" rel="self" type="application/rss+xml" />
	<link>http://www.adrianmccarthy.com/blog</link>
	<description>software engineer/aspiring author</description>
	<lastBuildDate>Sun, 18 Jul 2010 15:54:32 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Counting to a Billion</title>
		<link>http://www.adrianmccarthy.com/blog/?p=64</link>
		<comments>http://www.adrianmccarthy.com/blog/?p=64#comments</comments>
		<pubDate>Sat, 24 Apr 2010 17:42:37 +0000</pubDate>
		<dc:creator>Adrian</dc:creator>
				<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://www.adrianmccarthy.com/blog/?p=64</guid>
		<description><![CDATA[Let's count to a billion.]]></description>
			<content:encoded><![CDATA[<p>[This blog post is reconstructed from the <a href="http://www.archive.org">Internet Archive</a>'s copy of my <a href="http://web.archive.org/web/20071029190913/www.adrianmccarthy.com/blog/?p=59">original article</a> posted on April 7th, 2007. The original post was lost.]</p>
<p>Let&#8217;s count to a billion.</p>
<blockquote><pre>
#include &lt;iostream&gt;

void Count(const unsigned long limit) {
  DWORD ticStart = ::GetTickCount();
  unsigned long counter = 0;
  for (unsigned long i = 0; i &lt; limit; ++i) {
    ++counter;
  }
  DWORD ticStop = ::GetTickCount();

  std::cout &lt;&lt; "Counting took "
            &lt;&lt; ticStop &minus; ticStart
            &lt;&lt; "milliseconds."
            &lt;&lt; std::endl;
}

int main() {
  Count(1000 * 1000 * 1000);
  return 0;
}
</pre>
</blockquote>
<p>Computers are pretty fast. With optimization turned off, my computer reports that it took a mere 2547 milliseconds (or about 2.5 seconds) to count to a billion. With optimization turned on, the compiler realizes there are no side effects in the loop, so it replaces the loop with an assignment: <code>counter = limit;</code>, taking virtually no time.</p>
<p>In the ray tracer, I want to keep statistics. How many intersection tests were performed? How many rays per seconds were traced? How many of those were shadow rays? Essentially, this boils down to counting how many times certain operations are performed. From this experiment, I can see that incrementing a few counters won&#8217;t be a significant performance hit.</p>
<p>But the ray tracer is multithreaded. To keep n cores cranking, I&#8217;ve got n threads rendering different parts of the picture. So if I want an accurate count of how many times something happens, I&#8217;m going to have to put some sort of synchronization on the accesses to the counter.</p>
<blockquote><pre>
void CountWithCriticalSection(const unsigned long limit) {
  CRITICAL_SECTION cs;
  ::InitializeCriticalSection(&amp;cs);

  DWORD ticStart = ::GetTickCount();
  unsigned long counter = 0;
  for (unsigned long i = 0; i &lt; limit; ++i) {
    ::EnterCriticalSection(&amp;cs);
    ++counter;
    ::LeaveCriticalSection(&amp;cs);
  }
  DWORD ticStop = ::GetTickCount();
  ::DeleteCriticalSection(&amp;cs);

  std::cout &lt;&lt; "Critical section counting took "
            &lt;&lt; ticStop &minus; ticStart
            &lt;&lt; " milliseconds."
            &lt;&lt; std::endl;
}
</pre>
</blockquote>
<p>The example is still single threaded, but the code is now thread safe. The critical section prevents two threads from corrupting the counter by trying to modify it at the same time.</p>
<p>The bad news is that this example, optimized or not, took 73,719 milliseconds. Ouch. Thread safety has a price. And this is without any contention for the critical section. It would be worse with two threads incrementing the counter. Imagine how bad it would have been if we had used a mutex and had to make a billion round trips to kernel mode!</p>
<p>Fortunately, Windows provides a set of interlocked functions which can help us do simple, thread-safe operations like counting without the overhead of a critical section. One more version:</p>
<blockquote><pre>
void CountInterlocked(const unsigned long limit) {
  DWORD ticStart = ::GetTickCount();
  volatile long counter = 0;
  for (unsigned long i = 0; i &lt; limit; ++i) {
    ::InterlockedIncrement(&amp;counter);
  }
  DWORD ticStop = ::GetTickCount();

  std::cout &lt;&lt; "Interlocked counting took "
            &lt;&lt; ticStop &minus; ticStart
            &lt;&lt; " milliseconds."
            &lt;&lt; endl;
}
</pre>
</blockquote>
<p>This version scores significantly better at 37,390 milliseconds, just over half the time of the uncontested critical section. But that&#8217;s still a lot of overhead to take on while rendering.</p>
<p>And a little back-of-the-envelope calculation delivers even more bad news. Suppose one of the counters is supposed to be the number of intersection tests performed in the rendering job. If were computing images at hi-def resolution (1920 by 1080), that&#8217;s about 2 million pixels. If, for anti-aliasing, we oversample with say 16 rays per pixel, we&#8217;re up to about 32 million primary rays. Each primary might spawn a secondary reflection or refraction ray. Each of those 64 million rays might require, say, 10 shadow rays for shading. With a good acceleration structure, we might get away with as few as 4 intersections per ray. Next thing you know, we&#8217;ve exceeded the capacity of a 32-bit unsigned integer. If not for a single frame, then certainly once we start animating at 24 or 30 frames per second. So it looks like we&#8217;ll need 64 bits for at least some of our counters.</p>
<p>But, unless you&#8217;re on a 64-bit architecture, there aren&#8217;t 64-bit versions of the interlocked APIs. That means we&#8217;re back to critical sections for making the counters thread-safe. Obviously, we need to rethink this.</p>
<p>The key to good performance with multiple threads is to eliminate shared data as much as possible. Suppose instead of one counter, each thread had its own. Each thread would be able to increment its own counter without any synchronization concerns. Then, when the render is done, the independent counters could be summed to determine the total count. This adds a small amount of complexity and coordination, but not much, and the benefit should be worth it.</p>
<p>And this brings me back to my singleton post. I&#8217;m now paying the price for not taking my own advice. The ray tracer&#8217;s statistics are based on a set of counters kept in a singleton, so now I have to do some extra refactoring to distribute the counters among thread-specific objects.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.adrianmccarthy.com/blog/?feed=rss2&amp;p=64</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Test-Driven Development</title>
		<link>http://www.adrianmccarthy.com/blog/?p=37</link>
		<comments>http://www.adrianmccarthy.com/blog/?p=37#comments</comments>
		<pubDate>Sat, 05 Sep 2009 22:20:29 +0000</pubDate>
		<dc:creator>Adrian</dc:creator>
				<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://www.adrianmccarthy.com/blog/?p=37</guid>
		<description><![CDATA[A little test-driven development sample to show how helpful a unit test can be, even for a simple problem.]]></description>
			<content:encoded><![CDATA[<p>On a C++ programming forum, somebody asked a relatively simple question: How do you write a function that counts the number of lines in a text file? Most of the answers were friendly and helpful, but flawed.</p>
<p>As programmers, we often think of a problem as so trivial that we don&#8217;t take the time to think through the answers or to appreciate the subtlety of corner cases. In one of my favorite books, <em>Programming Pearls</em>, Jon Bentley talks about how hard it is for programmers to get fairly simple and routine problems correct on the first try. He writes:</p>
<blockquote><p>I&#8217;ve assigned this [binary search] problem in courses at Bell Labs and IBM. Professional programmers had a couple hours to [implement a binary search] in the language of their choice; a high-level pseudocode was fine. At the end of the specified time, almost all the programmers reported that they had the correct code for the task. We would then take thirty minutes to examine their code, which the programmers did with test cases. In several classes and with over a hundred programmers, the results were varied little; ninety percent of the programmers found bugs in their programs (and I wasn&#8217;t always convinced of the correctness of the code in which no bugs were found). [p. 36]</p></blockquote>
<p>Remember, these are <em>professional</em> programmers, in the language of their choice, with <em>hours</em> of time, messing up a <em>binary search</em>.</p>
<p>Notice the oh-so-common pattern here:</p>
<ol>
<li>Write code.</li>
<li>Declare that it works.</li>
<li>Test it and discover it&#8217;s broken.</li>
</ol>
<p>It&#8217;s enough to make you wonder if there&#8217;s a better way. Many people in the extreme programming and agile crowds would say that we&#8217;re doing it all out of order. Not only should &ldquo;declare it works&rdquo; come <em>after</em> testing, but probably so should writing code. So let&#8217;s take this seemingly trivial line-counting problem and apply a little test-driven development in C++.</p>
<p>First, let&#8217;s agree on an interface. I propose:</p>
<blockquote><pre><code>template &lt;typename InputIt&gt;
size_t CountLines(InputIt begin, InputIt end);
</code></pre>
</blockquote>
<p>That is, we&#8217;ll give the function a pair of iterators pointing to the beginning and end of the text we want examined, and the function will return the number of lines. (If you want to count the lines in a file, read the file into a std::string and call the function.) I&#8217;ve used size_t for the return type, as that&#8217;s typically unsigned (after all, the count will be 0 or more&mdash;it can&#8217;t be negative), and it&#8217;s generally as large an integer type as your platform will comfortably handle, so we shouldn&#8217;t have to worry about text consisting of too many lines. If you&#8217;re not a fan of the template parameters for the iterator types, feel free to re-write it with const char pointers.</p>
<p>Now that we know the interface, we will write the test function&mdash;even before we discuss <em>how</em> we&#8217;ll count lines. This function will iterate through a set of test cases, feed the input to CountLines, and check the return.</p>
<blockquote><pre><code>bool Test_CountLines() {
  struct TestCase {
    std::string input;
    size_t output;
  };

  const TestCase tests[] = {
    {&quot;Hello\nWorld\n&quot;, 2}
  };

  const size_t cTests = sizeof(tests) / sizeof(tests[0]);

  size_t cPassed = 0;
  size_t cFailed = 0;
  for (size_t i = 0; i &lt; cTests; ++i) {
    const TestCase &amp;test = tests[i];
    size_t cLines = CountLines(test.input.begin(), test.input.end());
    if (cLines == test.output) {
      ++cPassed;
    } else {
      std::cerr &lt;&lt; &quot;FAILURE&quot; &lt;&lt; std::endl
                &lt;&lt; &quot;Input \&quot;&quot; &lt;&lt; test.input &lt;&lt; '&quot;' &lt;&lt; std::endl
                &lt;&lt; &quot;Output &quot; &lt;&lt; cLines &lt;&lt; &quot; instead of &quot; &lt;&lt; test.output &lt;&lt; std::endl;
      ++cFailed;
    }
  }

  return cPassed == cTests &amp;&amp; cFailed == 0;
}</code></pre>
</blockquote>
<p>I&#8217;ve started us with one test case, and we can add more as we develop the function. Just to make sure our testing framework is solid, let&#8217;s stub out CountLines and a little main function to make sure it all compiles and runs.</p>
<blockquote><pre><code>template &lt;typename InputIt&gt;
size_t CountLines(InputIt /* begin */, InputIt /* end */) {
  size_t cLines = 0;
  return cLines;
}</code></pre>
</blockquote>
<p>I commented out the parameter names to avoid the &ldquo;unused parameter&rdquo; warnings. These will come into play shortly.</p>
<blockquote><pre><code>int main() {
  assert(Test_CountLines());
  return 0;
}</code></pre>
</blockquote>
<p>If you put all this together and run it, you&#8217;ll see that the test fails as expected. This is good, as we want to make sure we exercise the failure case of our test function to know that it works.</p>
<p>Some of you are probably saying that you could have already written a correct CountLines function by now. Maybe. Remember all those &ldquo;helpful&rdquo; answers on the programming forum? Remember all those professional developers attempting a binary search? Besides, it really didn&#8217;t take long to build this test infrastructure. If a bug ever does crop up in the function, we can easily debug it. When we fix a bug, we can immediately verify that we didn&#8217;t create a regression by re-checking every test case we&#8217;ve ever come up with. And you can add that new test case so that it never breaks again. If you change something fundamental, like the compiler or OS you&#8217;re using one, you can know with certainty whether or not it affects the behavior of your function.</p>
<p>Next we need test cases. Off the top of my head, here are some interesting cases we&#8217;ll have to design for:</p>
<ul>
<li>An empty string should have zero lines.</li>
<li>The count of a string with blank lines or empty lines (e.g., &ldquo;Hello\n\nWorld!\n&rdquo;) should include those blank lines.</li>
</ul>
<p>Doesn&#8217;t seem too hard yet, so let&#8217;s add those test cases.</p>
<blockquote><pre><code>const TestCase tests[] = {
  {&quot;&quot;, 0},
  {&quot;Hello\nWorld\n&quot;, 2},
  {&quot;Hello\n\nWorld\n&quot;, 3}
};</code></pre>
</blockquote>
<p>It seems pretty &ldquo;obvious&rdquo; that the way to count the lines is to count the number of newline (&#8216;\n&#8217;) characters in the string:</p>
<blockquote><pre><code>template &lt;typename InputIt&gt;
size_t CountLines(InputIt begin, InputIt end) {
  return std::count(begin, end, '\n');
}</code></pre>
</blockquote>
<p>Ta da! Test-driven development has led us directly to one of the common&mdash;but incorrect&mdash;answers given on the programming forum.</p>
<p>Consider the string &ldquo;Hello&rdquo;. That has zero newline characters, but most people would consider it to be one line long. Too bad we didn&#8217;t think of that while coming up with our test cases. Now that we have thought of it, the first thing to do is to add it to our test code.</p>
<blockquote><pre><code>const TestCase tests[] = {
  &hellip;
  {&quot;Hello&quot;, 1},
  &hellip;
};</code></pre>
</blockquote>
<p>We might be tempted to treat this new string as a special case.</p>
<blockquote><pre><code>// Ugly -- don't do this!
template &lt;typename InputIt&gt;
size_t CountLines(InputIt begin, InputIt end) {
  size_t cLines = std::count(begin, end, '\n');
  if (cLines == 0 &amp;&amp; begin != end) {
    cLines = 1;
  }
  return cLines;
}</code></pre>
</blockquote>
<p>While this hack will pass our tests, it&#8217;s ugly and still wrong. We&#8217;ve failed to realize that the &ldquo;Hello&rdquo; string is just a special case of not having a newline character on the last line in the string. (This is an extremely common bug in the wild. Many parsers choke if the last line of the input doesn&#8217;t end with a newline.) So we add another test case:</p>
<blockquote><pre><code>const TestCase tests[] = {
  &hellip;
  {&quot;Hello\nWorld&quot;, 2},
  &hellip;
};</code></pre>
</blockquote>
<p>When adding a test case, it&#8217;s good to think of counter-examples. For instance, if the last line of the string does end with a newline, that shouldn&#8217;t trigger an extra line. Fortunately, we&#8217;ve already got a test case for that.</p>
<p>Now our original approach is starting to look bad. Simply counting the newline characters, even with some hacky fix-ups for &ldquo;corner cases&rdquo;, isn&#8217;t going to work.</p>
<p>All is not lost. Yes, we have to completely re-think <em>how</em> we&#8217;re going to implement CountLines, but none of that invalidates the test framework we&#8217;ve built. When we come up with our new solution, we can immediately check to see if it solves the new test cases as well as the others we&#8217;ve already made. Suddenly it looks like the time we&#8217;ve put into the test framework is going to pay off.</p>
<p>There are a few ways to solve the line counting problem, but they all boil down to a state machine. Here&#8217;s my solution:</p>
<blockquote><pre><code>template &lt;typename InputIt&gt;
size_t CountLines(InputIt begin, InputIt end) {
  size_t cLines = 0;
  bool bStartOfLine = true;
  for ( ; begin != end; ++begin) {
    if (bStartOfLine) {
      ++cLines;
    }
    bStartOfLine = *begin == '\n';
  }
  return cLines;
}</code></pre>
</blockquote>
<p>In this case, there&#8217;s not much state&mdash;just a boolean. If we&#8217;re at the beginning of a line, and there&#8217;s anything on it (even a &#8216;\n&#8217;), then we need to count the line. After that, we simply need to figure out if the next character will be at the start of a line or not. This solution passes all five of our test cases.</p>
<p>Some say that you shouldn&#8217;t &ldquo;waste time&rdquo; on the corner cases, since, well, they&#8217;re <em>corner</em> cases. In my experience, though, if you get the corner cases right, then the mainstream cases generally just work. After all, the corner cases should just be degenerate versions of the mainstream case&mdash;or vice versa.</p>
<p>Uh oh, another bug. We&#8217;ve been considering &#8216;\n&#8217; to be the newline character. Text files on Multics-derived operating systems use a single ASCII line feed character (LF) to indicate a line break, but that&#8217;s far from universal. CP/M, DOS, Windows and a lot of Internet protocols require a carriage return (CR) followed by LF to mark a line break. C and C++ file i/o routines will translate whichever convention your platform uses to and from &#8216;\n&#8217;. Most compilers give &#8216;\n&#8217; the value 0&#215;0A, which happens to be the same as an ASCII LF. On Unix systems, the compiler&#8217;s i/o routines have to do no translation. On others, when you write &#8216;\n&#8217;, the output routine actually writes CR-LF, and when the input routine reads CR-LF, it returns &#8216;\n&#8217;. (Read all about <a href="http://en.wikipedia.org/wiki/Newline">newlines</a> on Wikipedia.)</p>
<p>But if we were to read in the data in binary mode (which could be faster), then we&#8217;ll see the actual bytes used in the file. So we have to add test cases. First, we&#8217;ll add the CR+LF cases. Then we&#8217;ll conditionally add ones with explicit LFs in case our compiler doesn&#8217;t use LF for &#8216;\n&#8217;.</p>
<blockquote><pre><code>const TestCase tests[] = {
  &hellip;
  {&quot;Hello\x0D\x0AWorld&quot;, 2},
  {&quot;Hello\x0D\x0AWorld\x0D\x0A&quot;, 2},
  {&quot;Hello\x0D\x0A\x0D\x0AWorld\x0D\x0A&quot;, 3},
#if '\n' != '\x0A'
  {&quot;Hello\x0AWorld&quot;, 2},
  {&quot;Hello\x0AWorld\x0A&quot;, 2},
  {&quot;Hello\x0A\x0AWorld\x0A&quot;, 3}
#endif
};</code></pre>
</blockquote>
<p>Happily, our latest version of CountLines works with these new examples. Essentially, the CR characters aren&#8217;t important to the algorithm, and our compiler does assign LF for &#8216;\n&#8217;.</p>
<p>If you did read the Wikipedia article, you know that there are several more newline conventions that we might want to support. Old Mac and Amiga files use just a CR, old IBM mainframes used NEL from the EBCDIC character set, Unicode introduced LINE SEPARATOR and PARAGRAPH SEPARATOR code points, etc. I&#8217;m sure you could imagine refining CountLines to handle these additional cases. Essentially, the state machine grows in complexity.</p>
<h3>Conclusion</h3>
<p>OK, this has been a long blog post, mostly because I&#8217;ve shown the iterative process necessary to solve the problem. What we&#8217;ve seen is that even the simplest problems might be more complex than we anticipate. The more thought we put into coming up with test cases, the more robust an implementation we were able to write. And when we had to start the implementation over from scratch, having a unit test framework helped us quickly ensure that the new implementation was at least as correct as the previous one.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.adrianmccarthy.com/blog/?feed=rss2&amp;p=37</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Servo Animation</title>
		<link>http://www.adrianmccarthy.com/blog/?p=24</link>
		<comments>http://www.adrianmccarthy.com/blog/?p=24#comments</comments>
		<pubDate>Sun, 09 Aug 2009 16:21:53 +0000</pubDate>
		<dc:creator>Adrian</dc:creator>
				<category><![CDATA[MazeBot]]></category>
		<category><![CDATA[Physics]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Projects]]></category>

		<guid isPermaLink="false">http://www.adrianmccarthy.com/blog/?p=24</guid>
		<description><![CDATA[How do you blend canned animations with physical simulation?]]></description>
			<content:encoded><![CDATA[<p>One of the (far too many) projects I&#8217;ve been working on is a video game. You might call it a sports simulations&mdash;then again, you might not, depending on your idea of what constitutes a sport. Nevertheless, it involves players waving sticks at balls, trying to get the balls to go in the right direction.</p>
<h3>Physics</h3>
<p>For the core of the game engine, I&#8217;ve built a physics simulator. Back in college, I had a tenuous grasp on Newtonian physics, which came in handy as I was earning my degree in physics. As with many things, you have to use it or lose it, and I haven&#8217;t exercised my knowledge of physics much since graduating. So, in addition to the figuring out how to translate conservation of energy into floating point math, I had to relearn some physics and, especially, some calculus. If you find yourself in the same boat, I recommend this series of articles from Chris Hecker as a warm-up:</p>
<ul>
<li><a href="http://chrishecker.com/Rigid_Body_Dynamics">Rigid Body Dynamics</a></li>
</ul>
<p>Those will help you (re-)learn the physics and math necessary to make a nice 2D simulator (think <a href="http://www.crayonphysics.com/">Crayon Physics</a>). With those as inspiration, these heavy-duty tutorials from David Baraff will help you build a nearly-complete 3D simulator:</p>
<ul>
<li><a href="http://www.cs.cmu.edu/~baraff/pbm/rigid1.pdf">Unconstrained Rigid Body Dynamics</a>&nbsp;[pdf]</li>
<li><a href="http://www.cs.cmu.edu/~baraff/pbm/rigid2.pdf">Nonpenetration Constraints</a>&nbsp;[pdf]</li>
</ul>
<p>My simulator is built almost directly from the latter two references. While these are hard-core articles, there is a lot more to this field. Fortunately for me, this was plenty to do the basic bouncing balls simulation that are necessary for my game.</p>
<p>At least, I thought it was. I have the balls bouncing, rolling, and smacking into each other, all under the control of the physical simulation. What I need now is to blend the simulation with canned animations and with input from the user. The question is, how do I handle the interaction of the animation-controlled objects with the simulation-controlled ones?</p>
<p>Consider a canned animation of a 3D character swinging a bat. There&#8217;s a ball hurtling toward the player&#8217;s avatar. The player presses a button to start the animation. Frame by frame, the bat&#8217;s position is updated. If the bat hits the ball, an impulse needs to be imparted to the ball. But since the swing is just a series of positions, we don&#8217;t have all the physical values necessary to compute an accurate force to apply to the ball. You could probably guesstimate the change in momentum and send the ball flying off in a plausible way, but what about the bat? If I continue with the animation of the player&#8217;s follow-through, you won&#8217;t see any recoil on the bat itself. The bat will continue on its trajectory as though the player had missed the ball.</p>
<p>This is a quandary I&#8217;ve been pondering off-and-on for a while. But after the <a href="http://www.adrianmccarthy.com/blog/?p=9">MazeBot</a> project, the answer came to me: servo control.</p>
<h3>Servo</h3>
<p>MazeBot has a <a href="http://mindstorms.lego.com/Products/Sensors/Compass%20Sensor.aspx">compass sensor</a> that gives its orientation in degrees with respect to magnetic north. At any point in time, MazeBot&#8217;s software has a desired orientation. The difference between the desired orientation and the measured orientation is the error. The error is used to compute how much power to apply to the left and right motors in order to turn the robot back to the desired heading. This is repeated many times per second in order to keep the robot on track. This is called servo control.</p>
<p>Now here&#8217;s the neat part. To execute a turn, the software &ldquo;animates&rdquo; the desired heading from its original value to the desired value. For example, if the robot is at heading 18 and it wants to turn 90 degrees, the software changes the desired heading to 19, then to 20, then 21, and so on, until it reaches 108. That&#8217;s it. It doesn&#8217;t directly issue any commands to the motors.</p>
<p>In the background, the servo controller is always running, trying its darndest to keep the robot aligned to the desired heading&mdash;even when the desired heading is a moving target. Thus the robot turns. How closely it follows the animated path depends on how well-tuned the servo controller is and how responsive the mechanism is.</p>
<h3>Servo Animation</h3>
<p>Suppose we applied the same idea to the animation of the bat. The bat could be just another object that the physics simulator controls. Rather than telling us where the bat <em>is</em>, the animation path tells us where we <em>want</em> the bat to be. We feed that desired position into a servo controller just like the desired heading is given to MazeBot&#8217;s servo controller. The servo controller returns the force (and torque) that should be applied to the bat to keep it on the animation path.</p>
<p>Now that the bat is a first-class citizen of the simulation, we have all the physical parameters we need to resolve any ball-bat collisions. The ball experiences a change in momentum and heads away to the outfield. The bat will also experience a recoil impulse causing it to momentarily fall behind the animation path. The servo controller will increase the forces to try to get the bat back on track, resulting in a swing that&mdash;while animation-driven&mdash;still responds in a realistically different way than if there had been no collision.</p>
<p>I haven&#8217;t tried this out yet. Given my project backlog, it might be a while, but I wanted to write up this idea while it was still fresh in my head. What do you think? Will it work?</p>
]]></content:encoded>
			<wfw:commentRss>http://www.adrianmccarthy.com/blog/?feed=rss2&amp;p=24</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>MazeBot</title>
		<link>http://www.adrianmccarthy.com/blog/?p=9</link>
		<comments>http://www.adrianmccarthy.com/blog/?p=9#comments</comments>
		<pubDate>Sat, 01 Aug 2009 02:17:41 +0000</pubDate>
		<dc:creator>Adrian</dc:creator>
				<category><![CDATA[MazeBot]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Projects]]></category>
		<category><![CDATA[Robotics]]></category>

		<guid isPermaLink="false">http://www.adrianmccarthy.com/blog/?p=9</guid>
		<description><![CDATA[My brother and I make it a point to get together about four weekends a year to do projects. We started this &#8220;tradition&#8221; a couple years ago, and it&#8217;s become something I look forward to every time.
Last weekend I met him in Southern California. He suggested we do a robotics projects, specifically, to make a [...]]]></description>
			<content:encoded><![CDATA[<p>My brother and I make it a point to get together about four weekends a year to do projects. We started this &ldquo;tradition&rdquo; a couple years ago, and it&rsquo;s become something I look forward to every time.</p>
<p>Last weekend I met him in Southern California. He suggested we do a robotics projects, specifically, to make a small robot that can navigate a maze. First we needed a maze, so we headed to <a href="http://www.homedepot.com/">Home Depot</a> with the idea of getting some lumber we could cut into various lengths and layout to make a reconfigurable maze. After settling on some 1&times;4 pine boards, we discovered some 2&times;16&times;6 concrete blocks. They worked beautifully, and were much cheaper than even the cheap wood we had originally selected.</p>
<p>To build the actual robot, which I dubbed MazeBot, we used LEGO (<a href="http://mindstorms.lego.com/">Mindstorms NXT</a>). Working with the NXT, which is the second generation of the LEGO robotics line, was much easier than trying to get the original Mindstorms brick to do much. We used <a href="http://www.robotc.net/">ROBOTC</a>, which is a C compiler from the folks at CMU made especially for robotics projects. We used <a href="http://en.wikipedia.org/wiki/Bluetooth">Bluetooth</a> to transfer the compiled programs from our development PC to the robot. The whole process was a snap, which made it very easy to do lots of iterations.</p>
<div id="attachment_13" class="wp-caption alignnone" style="width: 160px"><a href="http://www.adrianmccarthy.com/blog/wp-content/uploads/2009/07/2009-07-31-mazebot.jpg"><img src="http://www.adrianmccarthy.com/blog/wp-content/uploads/2009/07/2009-07-31-mazebot-150x150.jpg" alt="Adrian with MazeBot" title="MazeBot" width="150" height="150" class="size-thumbnail wp-image-13" /></a><p class="wp-caption-text">Adrian with MazeBot</p></div>
<p>Did I say lots of iterations?  We made eight major versions of the software (about four pages of C code) in one weekend. In the end, MazeBot could explore and map the maze. The next step would have been to give it more explicit goals, like finding a route to a particular cell in the maze, but we ran out of weekend. This video shows MazeBot in action.</p>
<p>The robot uses a <a href="http://mindstorms.lego.com/Products/Sensors/Ultrasonic%20Sensor.aspx">sonar sensor</a> in front to detect the maze walls. It has a <a href="http://mindstorms.lego.com/Products/Sensors/Compass%20Sensor.aspx">compass sensor</a> on a mast to determine its orientation. (The mast is necessary because the magnets in the drive motors interfered with the accuracy of the compass readings. Late in the weekend, we figured out that our mast had to be even taller to get good readings.) The software assumes everything in the maze is at right angles and that the robot begins aligned with one of the walls. The LEGO <a href="http://mindstorms.lego.com/Products/Accessories/Interactive%20Servo%20Motor.aspx">motors</a> also have feedback, which we used to determine how far the robot has traveled.</p>
<p><object width="400" height="300"><param name="allowfullscreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id=5773750&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=1&amp;show_portrait=0&amp;color=&amp;fullscreen=1" /><embed src="http://vimeo.com/moogaloop.swf?clip_id=5773750&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=1&amp;show_portrait=0&amp;color=&amp;fullscreen=1" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="400" height="300"></embed></object>
<p><a href="http://vimeo.com/5773750">MazeBot 8.0</a> from <a href="http://vimeo.com/user472154">Adrian</a> on <a href="http://vimeo.com">Vimeo</a>.</p>
<p>I certainly learned a lot about <a href="http://en.wikipedia.org/wiki/PID_controller">PID servo control</a>. Well, PI control anyway&mdash;our robot doesn&rsquo;t use a derivative term.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.adrianmccarthy.com/blog/?feed=rss2&amp;p=9</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
