The Socialhacker
//socialhacker.com/index.xml
Content on The Socialhacker
Hugo  gohugo.io
enus
anton@socialhacker.com (Anton Staaf)
anton@socialhacker.com (Anton Staaf)
Copyright © Anton Staaf. <a href="http://socialhacker.com/copyright/">Some rights reserved</a>.
Fri, 04 Aug 2017 00:00:00 +0000

Monoprice Mini Delta Setup (on Linux)
//socialhacker.com/posts/monoprice_mini_delta/
Fri, 04 Aug 2017 00:00:00 +0000
anton@socialhacker.com (Anton Staaf)
//socialhacker.com/posts/monoprice_mini_delta/
<p>I've never had a 3D printer before, but I've always known that I probably should. So when the new <a href="https://mpminidelta.monoprice.com/">Monoprice Mini Delta 3D Printer</a> was announced on <a href="https://www.indiegogo.com/projects/monopriceminideltaaffordablestarter3dprinter#/">Indiegogo</a> I jumped in and got one of the early shipments for $159. This writeup is partly reminder for me about the steps I took to get it working, and partly to help anyone else just getting started with the Mini Delta. I do all of my work on Linux, so I can't say anything about setting it up under macOS or Windows.</p>
<div class="gallery">
<a href = "//socialhacker.com/posts/3d_printed.jpeg">
<img src = "//socialhacker.com/thumbnails/posts/3d_printed.jpeg"
class = "postimage">
</a>
<a href = "//socialhacker.com/posts/zipper_pull.jpeg">
<img src = "//socialhacker.com/thumbnails/posts/zipper_pull.jpeg"
class = "postimage">
</a>
</div>
<p>I've printed a few copies of the test object (<a href="https://en.wikipedia.org/wiki/Manekineko">Manekineko</a>) because both of my kids wanted one. I also printed a replacement zipper pull for my daughter's backpack just in time for her to start school. To test out some tiny prints, and further interest my kids, I printed a few simple rings for them (and one for me when I mistook diameter for radius). The most roboticsrelated thing I've printed is a pulley for some <a href="http://www.ballchain.com/chain_sizes.html">#6 ball chain</a>. I'll be using that to make a simple XY pen plotter.</p>
<p>I didn't purchase any filament with the printer, so when it arrived I ran out to Fry's and picked up a 1 kg spool of yellow (my 1 year old was with me and he liked the yellow) Shaxon PLA (1.75mm diameter). I've had no problems with this filament, but have nothing to compare it with.</p>
<p>All in all, I love the Mini Delta. The build volume is not large, but I don't see that as a problem because if I actually tried to fill that volume I'd be printing for most of the day. And all the things I plan on printing are small mechanical components for my projects. For larger structural components I feel like laser cutting is the way to go. I did run into a few hiccups...</p>
<h2 id="issuesencountered">Issues encountered</h2>
<p>When I first unboxed and plugged in the machine I asked it to home its axes. While trying to home its print head, one of the three timing belt carriages got stuck at the top and made a nasty grinding noise, but managed to move back down, and then seemed fine. I should have investigated more at that time, but wanted to get to printing. So I started the sample print job that came on the SD card. Unfortunately, the sticking at the top of one of the carriages caused the machine to not quite know where the print head was, which made one side of the bed seem lower than it actually was, which caused the print head to scrape the bed while printing the initial raft. The first image below is of the damage to the print bed, pretty minimal actually, and it hasn't affected print adhesion. The second image is a picture of what I think is the culprit: the optical endstop sensor at the top of the column. If you look carefully at the three conductor connector, you can see that the header shroud is not symmetric, in fact the left side has been cut away, manually. I checked and this has been done to all three such connectors at the top of each column. If this manual step had not been done the bearing carriage would hit the header shroud and prevent the carriage from reaching the fully homed position. My guess is that this was a last minute change in parts or placement on the PCB, and this interference wasn't noticed until a few machines were manufactured. And it was likely much cheaper to have someone carve away the offending plastic than to remake the endstop boards. So, my guess is that this endstop header shroud was not fully clearing the carriage, resulting in a bind that caused the stepper controller to lose some steps, resulting in the hot end crash.</p>
<div class="gallery">
<a href = "//socialhacker.com/posts/bed_scrape.jpeg">
<img src = "//socialhacker.com/thumbnails/posts/bed_scrape.jpeg"
class = "postimage">
</a>
<a href = "//socialhacker.com/posts/mini_delta_optical_sensor.jpeg">
<img src = "//socialhacker.com/thumbnails/posts/mini_delta_optical_sensor.jpeg"
class = "postimage">
</a>
</div>
<p>The auto bed level sensing is great, though each time it touches down it leaves a small amount of plastic stuck to the bed. I have been removing that between prints, if I didn't I imagine it would throw off the level sensing and cause problems.</p>
<p>While tweaking the tools (described below) to match this machine I generated a few files that directed the print head outside of the workable area, crashing it into parts of the machine that it really shouldn't be touching. I'm amazed that everything seems to be working fine now (I'm sure there's some extra wear on the timing belts and pulleys). I feel like the printer firmware should enforce limits on the print head movement to protect itself.</p>
<h2 id="toolsused">Tools used</h2>
<p>Setting up the printer was not trivial, mainly because I didn't want to use the provided Windows executable. Since I've never had a 3D printer before, I had to decide which tools to use. There are roughly three steps to making something new with a 3D printer:</p>
<p>First you need to design your awesome new object. This is done with a CAD (Computer Aided Design) tool, and the result is a file that describes the geometry of the object. You can also download premade objects from sites like <a href="https://www.thingiverse.com">Thingiverse</a>. It could be as simple as a file that specifies that it is a cube 1cm on a side. For this I used OpenSCAD.</p>
<p>Second the geometry needs to be turned into a sequence of operations for the printer to use to lay down the plastic needed to make the object. This is called slicing, and is where decisions like how the inside should be filled, how thick each layer should be, and whether some additional support or build platform should be added are made, among many others. The result of this step is almost always a sequence of primitive machine operations called <a href="https://en.wikipedia.org/wiki/Gcode">Gcode</a>. I used Cura to handle this step.</p>
<p>Finally the Gcode needs to be sent to the printer. The Mini Delta has three options here: you can transfer the file with an SD card, you can upload the file using a web interface exposed over WiFi, or you can send the instructions over USB. I used the SD card for the first few prints, tried to get the web interface to work <sup class="footnoteref" id="fnref:1"><a class="footnote" href="#fn:1">1</a></sup>, and finally settled on using the USB interface. The USB interface uses one of the standard serial over USB protocols, but you can't just cat the Gcode file over the serial port, there is a bit more to it. I found that Octoprint worked well for this.</p>
<h3 id="openscadhttpwwwopenscadorg"><a href="http://www.openscad.org/">OpenSCAD</a></h3>
<p>OpenSCAD is not for everyone, it trades constraint based modeling for programmatic control over the model <sup class="footnoteref" id="fnref:2"><a class="footnote" href="#fn:2">2</a></sup>. As such it's more of a programmer's tool than a modeling tool. But it is fine for making some objects to print quickly. And I already knew how to use it because it's also what I've used in the past to model objects for laser cutting. Below is a screen shot of the zipper pull rendered in OpenSCAD.</p>
<div class="gallery">
<a href = "//socialhacker.com/posts/openscad_zipper_pull.png">
<img src = "//socialhacker.com/thumbnails/posts/openscad_zipper_pull.png"
class = "postimage">
</a>
</div>
<p>You can find some of the OpenSCAD files I've made on <a href="https://www.thingiverse.com/socialhacker/designs">Thingiverse</a>.</p>
<p>Eventually I think I'll be using <a href="http://solvespace.com/index.pl">Solvespace</a> for all my mechanical CAD work. It is a full parametric modeler, which is a very powerful way to create objects.</p>
<h3 id="curahttpsultimakercomenproductscurasoftware"><a href="https://ultimaker.com/en/products/curasoftware">Cura</a></h3>
<p>I selected Cura mainly because it's what Monoprice shipped on the SD card. First I created a custom printer. This is largely based on the CURA_CONFIG.ini file supplied with the printer on the SD card. But that file is for an older version of Cura that is also supplied on the SD card (as a Windows executable). So some changes had to be made. Unfortunately I wasn't able to find a way of writing a config file and importing it into Cura; I had to enter the printer config manually in the GUI. Below is the resulting configuration file that Cura saves as <code>~/.local/share/cura/master/definition_changes/Custom+FDM+printer_settings.inst.cfg</code>.</p>
<pre><code class="languagessh_config">[general]
version = 2
name = Custom FDM printer_settings
definition = custom
[metadata]
type = definition_changes
setting_version = 1
[values]
gantry_height = 0
machine_center_is_zero = True
machine_depth = 120
machine_end_gcode = ;End GCode
M104 S0 ;extruder heater off
M140 S0 ;heated bed heater off (if you have it)
G91 ;relative positioning
G1 E1 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure
G1 Z+0.5 E5 X20 Y20 F4800 ;move Z up a bit and retract filament even more
G28 X0 Y0 ;move X/Y to min endstops, so the head is out of the way
M84 ;steppers off
G90 ;absolute positioning
machine_head_with_fans_polygon = [[0, 0], [0, 0], [0, 0], [0, 0]]
machine_heated_bed = True
machine_height = 120
machine_shape = elliptic
machine_start_gcode = ;Sliced at: {day} {date} {time}
;Basic settings: Layer height: {layer_height} Walls: {wall_thickness} Fill: {infill_sparse_density}
;Print time: {print_time}
;Filament used: {filament_amount}m {filament_weight}g
;Filament cost: {filament_cost}
G21 ;metric values
G90 ;absolute positioning
M82 ;set extruder to absolute mode
M107 ;start with the fan off
G28 ;Home
G29 C0.8 Z0.3 ;Auto level print platform
G1 Z15.0 F4800 ;move the platform down 15mm
G92 E0 ;zero the extruded length
G1 F200 E3 ;extrude 3mm of feed stock
G92 E0 ;zero the extruded length again
G1 F4800
machine_width = 120
material_diameter = 1.75
</code></pre>
<p>Then I created a custom profile based on the draft profile and set the build plate adhesion type to "Raft", with an extra margin of 5mm. I found that without the raft it was extremely difficult to remove the prints. The raft also seems to protect the build plate a bit (the printing on the build plate sticks to the bottom of the print a bit). This results in a configuration file saved as <code>~/.local/share/cura/master/quality/custom_draft+quality+pla.inst.cfg</code>. Cura does provide an export/import option for profiles, but it generates a ZIP file with a bunch of dummy profiles for up to eight extruders, not a simple text description like I was expecting. It seems easier to handle this step in the GUI as well.</p>
<pre><code class="languagessh_config">[general]
version = 2
name = Draft Quality PLA
definition = fdmprinter
[metadata]
type = quality_changes
quality_type = draft
setting_version = 1
[values]
adhesion_type = raft
raft_margin = 5
</code></pre>
<p>Fortunately it is possible to easily import a filament description. Below is the material description file that I created for Cura.</p>
<pre><code class="languagexml"><?xml version='1.0' encoding='utf8'?>
<fdmmaterial version="1.3" xmlns="http://www.ultimaker.com/material">
<metadata>
<name>
<brand>Shaxon</brand>
<material>PLA</material>
<color>Yellow</color>
<label>yellow</label>
</name>
<setting_version>1</setting_version>
<GUID>ea2fff891826406fbab04e612f2e5e20</GUID>
<version>1</version>
<color_code>#f4f442</color_code>
<description></description>
<adhesion_info></adhesion_info>
<compatible>True</compatible>
</metadata>
<properties>
<density>1.25</density>
<diameter>1.75</diameter>
</properties>
<settings>
<setting key="print temperature">190.0</setting>
<setting key="heated bed temperature">70.0</setting>
<setting key="retraction amount">4.0</setting>
<setting key="retraction speed">80.0</setting>
<setting key="standby temperature">150.0</setting>
<setting key="print cooling">100.0</setting>
</settings>
</fdmmaterial>
</code></pre>
<h3 id="usbconnection">USB connection</h3>
<p>The generic Linux usb serial driver doesn't yet know about the USB VID:PID pair for this printer, so in order to connect you need to provide it with them. My solution was to create a simple pair of UDEV rules.</p>
<pre><code class="languagebash">#
# Add USB VID/PID for Monopride Mini Delta
#
ACTION=="add", SUBSYSTEM=="usb", ATTR{idVendor}=="cfce", ATTR{idProduct}=="0300", RUN+="/usr/bin/modprobe usbserial", RUN+="/bin/sh c 'echo $attr{idVendor} $attr{idProduct} > /sys/bus/usbserial/drivers/generic/new_id'"
#
# Construct a symlink to the TTY generated for the printer.
#
SUBSYSTEM=="tty", ATTRS{idVendor}=="cfce", ATTRS{idProduct}=="0300", SYMLINK+="monoprice_mini_delta"
</code></pre>
<p>I saved this as <code>/etc/udev/rules.d/51monopriceminidelta.rules</code>, reloaded UDEV's rule database with <code>sudo udevadm control reload</code>, and finally unplugged and plugged back in the printer USB cable. That gave me a handy symlink (<code>/dev/monoprice_mini_delta</code>) to use. To test that it worked I used screen to open the serial device (<code>screen /dev/monoprice_mini_delta 115200</code>) and sent a few <a href="https://en.wikipedia.org/wiki/Gcode">Gcode</a> commands to the printer. In particular I sent G28 to home the axes, and M115 to get the machine information. For me M115 returns:</p>
<pre><code class="languagebash">NAME. Malyan
VER: 3.7
MODEL: M300
HW: HG01
BUILD: Jun 26 2017 19:04:37
</code></pre>
<p>If you've never used screen, you can exit with CtrlA followed by '\'.</p>
<h3 id="octoprinthttpoctoprintorg"><a href="http://octoprint.org/">Octoprint</a></h3>
<p>Setting up Octoprint on Arch Linux (my preferred desktop distribution) is pretty easy if you're familiar with the AUR. The package to install is octoprintvenv. And once installed you can enable and start the service with:</p>
<pre><code class="languagebash">sudo systemctl enable octoprint.service
sudo systemctl start octoprint.service
</code></pre>
<p>Be warned: this runs Octoprint as root, probably not the best decision securitywise. By default Octoprint will start a web server listening to just the local machine on port 5000. So navigate over to <code>http://localhost:5000</code> and you should be greeted with a nice GUI. The first thing to do is to connect to the printer. Use <code>/dev/monoprice_mini_delta</code> for the serial port, and <code>115200</code> for the baud rate. Once connected, go to the Control tab and try something safe, like turning the fan on and off.</p>
<p>The Octoprint GUI is pretty selfexplanatory at this point; you can upload Gcode files and print them. You also have a number of options for monitoring the print job, including graphs of bed and extruder temperature, visualization of the Gcode instructions sent to the printer, and a raw stream of instructions.</p>
<p>The Control tab is also a lot of fun, but be careful, the Mini Delta's firmware doesn't prevent you from running the print head into the edge of the frame or down into the print bed. So make small moves until you have a good understanding of the machine.</p>
<div class="footnotes">
<hr>
<ol>
<li id="fn:1"><p>I managed to get the WiFi working easily enough, but was not able to upload
a file using the web UI. I didn't spend much time debugging that as I
switched to using OctoPrint over USB and that has been rock solid.
OctoPrint's UI is also much more polished.</p>
<a class="footnotereturn" href="#fnref:1"><sup>[return]</sup></a></li>
<li id="fn:2"><p>This may be a false dichotomy, but I haven't seen a CAD programming language
that allows for the creation of constraints. A constraint based CAD
language would be interesting to work in.</p>
<a class="footnotereturn" href="#fnref:2"><sup>[return]</sup></a></li>
</ol>
</div>

Interactive Explosions using Exponential Decay
//socialhacker.com/posts/breaker/interactive_explosions/
Mon, 06 Mar 2017 00:00:00 +0000
anton@socialhacker.com (Anton Staaf)
//socialhacker.com/posts/breaker/interactive_explosions/
<p>I have been working on a game recently, and I ran into some interesting math
along the way. I wanted an explosion animation that started out fast, and as
it got larger it would get slower. Below you can click, drag or swipe to
create the explosions I ended up building.</p>
<div class="viewport shockwaveview" id=""></div>
<p>For simplicity, I am rendering the explosion as a ring, with expanding inner
and outer radii. I wanted the rate of expansion of the two radii to start
fast and end slow, but this could just as easily be applied to a collection of
particles. One possible formula for velocity would be a linear ramp, changing
from the initial to the final velocity in equal steps over the animation. That
is, a constant change in velocity.</p>
<p><span class="math">\[\frac{dV(t)}{dt} = \frac{V_T  V_0}{T}\]</span></p>
<p>But that didn't have the effect I was looking for; I wanted the leading edge of
the ring to be moving really quickly and to slow down really quickly. And as
it was near the end of the animation, moving more slowly, I wanted it to be
slowing down more slowly as well. I wanted the change in velocity to be
proportional to the current velocity.</p>
<p><span class="math">\[
\begin{equation}\label{eqn:exponential_decay}
\frac{dV(t)}{dt} = \lambda V(t)
\end{equation}
\]</span></p>
<p>This differential equation, known as an
<a href="https://en.wikipedia.org/wiki/Exponential_decay">Exponential Decay</a>, is
conventionally written with a negative sign so that the proportionality
constant, <span class="math">\(\lambda\)</span>, will be positive. When <span class="math">\(\lambda\)</span> is positive it
continually subtracts a proportion of the velocity from itself, so when the
velocity is large, the portion subtracted will be large, and when the
velocity is small, the portion subtracted will be small. For completeness
we'll also need a differential equation that relates position and velocity.</p>
<p><span class="math">\[
\begin{equation}\label{eqn:position_diffeq}
\frac{dX(t)}{dt} = V(t)
\end{equation}
\]</span></p>
<p>The combination of <span class="math">\(\eqref{eqn:exponential_decay}\)</span> and
<span class="math">\(\eqref{eqn:position_diffeq}\)</span> is a system of differential equations; it says
that the change in something's velocity (in our case the two ring radii) at some
time will be proportional to the thing's velocity at that time. It also says
that the change in the thing's position at some time is the thing's velocity.
You can use these equations exactly as they are, via numeric integration. You
iteratively update the velocity and position of the value you are simulating.
The simplest way to do the update would be with the
<a href="https://en.wikipedia.org/wiki/Euler_method">Euler method</a>. You would select
a small increment in time (a timestep) and move the simulation forward by that
amount of time over and over again. For every timestep you update velocity by
evaluating <span class="math">\(\eqref{eqn:exponential_decay}\)</span>, and then position by evaluating
<span class="math">\(\eqref{eqn:position_diffeq}\)</span>. But if you want to know the position or
velocity at a specific time you'll need to rerun the simulation from the
beginning to get it, which could be very costly if you have selected a small
timestep, which you would have to do to ensure an accurate simulation.
Alternatively you could store all previous steps of the simulation, which would
take a lot of memory. Either way, what values should you use for <span class="math">\(\lambda\)</span>
and the initial position and velocity? A better approach (at least for my
needs) is to solve this differential equation analytically, and use the result
to pick initial values and to evaluate position and velocity at arbitrary times.</p>
<p>Here is another version of the same expanding ring, rendered using the
awesome online calculator <a href="https://www.desmos.com/">Desmos</a>. You can manually
control the time slider (if you can grab it) to get a feel for how the two
exponentials control the inner and outer radii of the ring.</p>
<iframe src = "https://www.desmos.com/calculator/xm4ltfryqz?embed"
id = ""
class = "desmosiframe">
</iframe>
<p>So where's the interesting math? It turns out that picking the initial
position, velocity, and <span class="math">\(\lambda\)</span> values to get a goodlooking explosion
takes some care. For one thing, I wanted to make the final positions of the two
exponenitals that control the inner and outer radii equal. I could have done
that by trial an error, maybe, but there's a better way. In this post I'll go
through solving <span class="math">\(\eqref{eqn:exponential_decay}\)</span> and
<span class="math">\(\eqref{eqn:position_diffeq}\)</span> for a number of different parameters. We'll
want an equation that can tell us the radius at a given time in the simulation.
We'll also want to be able to compute initial velocity given some more
intuitive parameters that make specifying the explosion simpler. In this case,
it turns out to be easier to specify the final velocity, duration of explosion,
and amount that the ring should expand. Given these, the initial velocity and
<span class="math">\(\lambda\)</span> are completely defined.</p>
<h2 id="velocity">Velocity</h2>
<p>The first step will be to solve <span class="math">\(\eqref{eqn:exponential_decay}\)</span> so that we
have an equation for velocity at an arbitrary time. This is a pretty simple
differential equation, and we can solve it directly by integration.</p>
<button dataopen = Hide derivation
dataclosed = Show derivation
class = "hiddenshortcodebutton">
Show derivation
</button>
</section>
<section class="content
hiddenshortcodewrapper
startclosed
">
<div class="hiddenshortcodecontent" style="overflow: auto">
<p>First multiply both sides of <span class="math">\(\eqref{eqn:exponential_decay}\)</span> by <span class="math">\(dt\)</span> and
divide by <span class="math">\(V(t)\)</span>.</p>
<p><span class="math">\[\frac{1}{V(t)} dV(t) = \lambda dt\]</span></p>
<p>Integrate both sides and collect the integration constants on the right. The
integral of <span class="math">\(\frac{1}{u}du\)</span> is <span class="math">\(log(u) + C\)</span>, and the integral of <span class="math">\(a du\)</span>
is <span class="math">\(a u + C\)</span>.</p>
<p><span class="math">\[log(V(t)) = \lambda t + C\]</span></p>
<p>We want to get an equation for <span class="math">\(V(t)\)</span> so we need to get it out of the
logarithm on the left; exponentiate both sides.</p>
<p><span class="math">\[V(t) = e^{\lambda t + C}\]</span></p>
<p>We just have one step left; we need to determine what <span class="math">\(C\)</span> is. To find out
what <span class="math">\(C\)</span> is we compute the velocity at time zero (<span class="math">\(V_0\)</span>).</p>
<p><span class="math">\[V_0 := V(0) = e^C\]</span></p>
<p>So we can break the exponential up into two factors, and replace the second
factor (<span class="math">\(e^C\)</span>) with <span class="math">\(V_0\)</span>. We can see that <span class="math">\(C\)</span> was just the logarithm
of our initial velocity (<span class="math">\(V_0\)</span>).</p>
</div>
</section>
<section class="content">
<p>The result is the solution for velocity at any time <span class="math">\(t\)</span>.</p>
<p><span class="math">\[
\begin{equation}\label{eqn:velocity}
V(t) = V_0 e^{\lambda t}
\end{equation}
\]</span></p>
<p>Nothing too surprising here; this tells us how a value changes over time if it
is continually being acted on in proportion to itself. Here is the same
function written in Dart<sup class="footnoteref" id="fnref:1"><a class="footnote" href="#fn:1">1</a></sup>. This is one method from a class called
<a href="//socialhacker.com/source/breaker/web/exponential_rate_source/">ExponentialRate</a> that I am using
to model this system of differential equations in the game. The complete
source for <a href="//socialhacker.com/source/breaker/web/exponential_rate_source/">ExponentialRate</a>
can be found <a href="//socialhacker.com/source/breaker/web/exponential_rate_source/">here</a>.</p>
<pre><code class="languagedart">///
/// Return the rate of change of the value at a given time.
///
/// Time can be negative, positive, or zero, it should also be able to be
/// positive or negative infinity, but I haven't verified that Dart's exp
/// function correctly handles those cases.
///
double rate(double time) => initial_rate * exp(lambda * time);</code></pre>
<h2 id="position">Position</h2>
<p>Next we want to know about the position over time, both so that we can query it
for animations and so that we can solve the equation for our initial velocity.
Now that we have <span class="math">\(\eqref{eqn:velocity}\)</span>, which is an equation for <span class="math">\(V(t)\)</span>,
we can substitute it into <span class="math">\(\eqref{eqn:position_diffeq}\)</span>, our definition of
position. This gives us a differential equation that we can solve.</p>
<button dataopen = Hide derivation
dataclosed = Show derivation
class = "hiddenshortcodebutton">
Show derivation
</button>
</section>
<section class="content
hiddenshortcodewrapper
startclosed
">
<div class="hiddenshortcodecontent" style="overflow: auto">
<p><span class="math">\[
\begin{equation}\label{eqn:exponential_position_diffeq}
\frac{dX(t)}{dt} = V_0 e^{\lambda t}
\end{equation}
\]</span></p>
<p>Again, this is a pretty simple differential equation; the only thing that we
have to remember is</p>
<p><span class="math">\[\int e^u du = e^u + C.\]</span></p>
<p>But to apply this integral we need to make sure that <span class="math">\(du\)</span> really is the
derivative of <span class="math">\(u\)</span>. In our case;</p>
<p><span class="math">\[u = \lambda t\]</span></p>
<p>Differentiate this with respect to <span class="math">\(t\)</span> and we get</p>
<p><span class="math">\[\frac{du}{dt} = \lambda\]</span></p>
<p>or</p>
<p><span class="math">\[du = \lambda dt.\]</span></p>
<p>This means that</p>
<p><span class="math">\[
\begin{equation}\label{eqn:exponential_integral}
\int \lambda e^{\lambda t} dt = e^{\lambda t} + C.
\end{equation}
\]</span></p>
<p>We want to manipulate <span class="math">\(\eqref{eqn:exponential_position_diffeq}\)</span> until we can
apply this integral to the right side. First multiply
<span class="math">\(\eqref{eqn:exponential_position_diffeq}\)</span> by <span class="math">\(dt\)</span>.</p>
<p><span class="math">\[dX(t) = V_0 e^{\lambda t} dt\]</span></p>
<p>The right hand side is missing a <span class="math">\(\lambda\)</span> term, we can introduce one by
multiplying the right hand side by <span class="math">\(\frac{\lambda}{\lambda} = 1\)</span>.</p>
<p><span class="math">\[dX(t) = \frac{V_0}{\lambda} \lambda e^{\lambda t} dt\]</span></p>
<p>At this point we can integrate both sides.</p>
<p><span class="math">\[\int dX(t) = \int \frac{V_0}{\lambda} \lambda e^{\lambda t} dt\]</span></p>
<p>The left hand side is simply the integral of the derivative of <span class="math">\(X(t)\)</span>. That
will be <span class="math">\(X(t) + C_0\)</span>, where <span class="math">\(C_0\)</span> is an arbitrary constant that was lost by
the differentiation. On the right hand side we can move the constant
<span class="math">\(\frac{V_0}{\lambda}\)</span> out of the integral.</p>
<p><span class="math">\[X(t) + C_0 = \frac{V_0}{\lambda} \int \lambda e^{\lambda t} dt\]</span></p>
<p>The integral now matches <span class="math">\(\eqref{eqn:exponential_integral}\)</span>.</p>
<p><span class="math">\[X(t) + C_0 = \frac{V_0}{\lambda} (e^{\lambda t} + C_1)\]</span></p>
<p>Expand the product on the right, and move all of the terms that depend on our
unknown integration constants to the right.</p>
<p><span class="math">\[X(t) = \frac{V_0}{\lambda} e^{\lambda t} + (\frac{V_0}{\lambda} C_1  C_0)\]</span></p>
<p>We can replace <span class="math">\(\frac{V_0}{\lambda} C_1  C_0\)</span> with a new constant <span class="math">\(C\)</span>.</p>
<p><span class="math">\[X(t) = \frac{V_0}{\lambda} e^{\lambda t} + C\]</span></p>
<p>To find the combined integration constant solve for initial position <span class="math">\(X_0\)</span>.</p>
<p><span class="math">\[
\begin{align*}
X_0 :&= X(0)\\
&= \frac{V_0}{\lambda} e^0 + C\\
&= \frac{V_0}{\lambda} + C
\end{align*}
\]</span></p>
<p>So our integration constant is</p>
<p><span class="math">\[C = X_0  \frac{V_0}{\lambda}.\]</span></p>
<p>And the final solution for our position over time is</p>
<p><span class="math">\[X(t) = \frac{V_0}{\lambda} e^{\lambda t} + X_0  \frac{V_0}{\lambda}.\]</span></p>
<p>This can be simplified by factoring out <span class="math">\(\frac{1}{\lambda}\)</span>.</p>
</div>
</section>
<section class="content">
<p>The result is an explicit equation for <span class="math">\(X(t)\)</span>.</p>
<p><span class="math">\[
\begin{equation}\label{eqn:position}
X(t) = X_0 + \frac{1}{\lambda} (V_0 e^{\lambda t}  V_0)
\end{equation}
\]</span></p>
<p>Below you can experiment with <span class="math">\(\eqref{eqn:velocity}\)</span> and
<span class="math">\(\eqref{eqn:position}\)</span>, try changing <span class="math">\(X_0\)</span>, <span class="math">\(V_0\)</span>, <span class="math">\(\lambda\)</span>, and the
total time of the simulation. <span class="math">\(V_0\)</span> is controlled by manipulating the tangent
line to the graph at the origin.</p>
<iframe src = "https://www.desmos.com/calculator/f1c9s0eity?embed"
id = ""
class = "desmosiframe">
</iframe>
<p>I noticed that the first term (<span class="math">\(V_0 e^{\lambda t}\)</span>) is just
<span class="math">\(\eqref{eqn:velocity}\)</span>, so I used that in its place.</p>
<p><span class="math">\[
\begin{equation}\label{eqn:position_from_rate}
X(t) = X_0 + \frac{1}{\lambda}(V(t)  V_0)
\end{equation}
\]</span></p>
<p>There is something very pleasing about this equation; the change in position is
proportional to the change in velocity. But this form of the equation has some
issues. One thing to note about this solution is that it doesn't work if
<span class="math">\(\lambda\)</span> is equal to zero. Fortunately <span class="math">\(\eqref{eqn:exponential_decay}\)</span>
then becomes trivial (<span class="math">\(\frac{dV(t)}{dt} = 0\)</span>), and the solutions are
<span class="math">\(V(t) = V_0\)</span> and <span class="math">\(X(t) = X_0 + V_0 t\)</span>. However, when I thought about this
more, I realized that this substitution of <span class="math">\(\eqref{eqn:velocity}\)</span> had hidden
a numerical issue in the implementation as well. If we start back with
<span class="math">\(\eqref{eqn:position}\)</span> and rearrange a little by factoring out <span class="math">\(V_0\)</span> and
moving <span class="math">\(\frac{1}{\lambda}\)</span> in we can see more clearly what the problem is.</p>
<p><span class="math">\[X(t) = X_0 + V_0 \frac{e^{\lambda t}  1}{\lambda}\]</span></p>
<p>The right term numerator is <span class="math">\(e^{\lambda t}  1\)</span>, which, for values of
<span class="math">\(\lambda t\)</span> close to zero, can lead to
<a href="https://en.wikipedia.org/wiki/Loss_of_significance">Loss of Significance</a>
because we are subtracting two numbers that are nearly identical (<span class="math">\(e^0 = 1\)</span>).
It wasn't clear at first to me how to handle this; in C/C++ I would have used
<a href="http://man7.org/linux/manpages/man3/expm1.3.html">expm1</a> and then used the
trivial solutions for <span class="math">\(\eqref{eqn:exponential_decay}\)</span> and
<span class="math">\(\eqref{eqn:position_diffeq}\)</span> when <span class="math">\(\lambda\)</span> was zero, but there would
still be a possible problem with the division when <span class="math">\(\lambda\)</span> is very close to
zero because both numerator and denominator would be approaching zero. In
hopes that I could come up with an alternate representation that would work for
all values of <span class="math">\(\lambda\)</span> and <span class="math">\(t\)</span>, I started to work with the infinite sum
representation of the exponential function.</p>
<p><span class="math">\[\def\exp_sum#1#2{\sum_{k=#1}^{\infty} \frac{#2^k}{k!}}\]</span></p>
<p><span class="math">\[e^x = \exp_sum{0}{x}\]</span></p>
<p>I used this sum in place of the exponential in <span class="math">\(\eqref{eqn:position}\)</span>.</p>
<p><span class="math">\[X(t) = X_0 + \frac{V_0}{\lambda} (\exp_sum{0}{(\lambda t)}  1)\]</span></p>
<p>The first term in the sum is just one.</p>
<p><span class="math">\[e^{\lambda t} = 1 + \exp_sum{1}{(\lambda t)}\]</span></p>
<p>That one cancels out the subtraction by one, leaving all of the remaining terms
from <span class="math">\(\numrange{1}{\infty}\)</span>. All of those terms have at least one
<span class="math">\(\lambda\)</span> in them, so I was able to divide the sum by <span class="math">\(\lambda\)</span>,
canceling out one of the <span class="math">\(\lambda\)</span> factors in each term. The result had no
divisions by <span class="math">\(\lambda\)</span>. Nice.</p>
<p><span class="math">\[X(t) = X_0 + V_0 (\sum_{k=1}^{\infty} \frac{\lambda^{k1} t^k}{k!})\]</span></p>
<p>Then I saw that I could pull a <span class="math">\(t\)</span> out of the sum as well. And I could shift
the sum index (<span class="math">\(k\)</span>) by one, so that the sum started at zero again.</p>
<p><span class="math">\[X(t) = X_0 + V_0 t (\sum_{k=0}^{\infty} \frac{(\lambda t)^k}{(k + 1)!})\]</span></p>
<p>The sum now looked so much like an exponential by itself that I was distracted
into thinking that I could do something to recover a simple exponential form,
with some additional damping factor (accounting for the <span class="math">\(+1\)</span> in the
factorial), that didn't have the division by zero problem that the original
version had. Eventually I realized that the pulling out of <span class="math">\(t\)</span> was the
crucial piece that I had missed at first. I went back to
<span class="math">\(\eqref{eqn:position}\)</span> to see what would happen when I took a <span class="math">\(t\)</span> out of
the second factor.</p>
<p><span class="math">\[
\begin{equation}\label{eqn:position_with_hex}
X(t) = X_0 + V_0 t \frac{e^{\lambda t}  1}{\lambda t}
\end{equation}
\]</span></p>
<p>I had to put a <span class="math">\(t\)</span> in the denominator, which nicely turns the problematic
portion into a one variable problem. No longer did I have to treat
<span class="math">\(\lambda\)</span> and <span class="math">\(t\)</span> as separate variables; I could just lump them together
and work on solving <span class="math">\(\frac{e^x1}{x}\)</span>, which at this point I feel like needs
a name. If anyone knows of a name for this particular function<sup class="footnoteref" id="fnref:2"><a class="footnote" href="#fn:2">2</a></sup> I would be
interested, for now I'm calling it a hexponential, or <span class="math">\(hex(x)\)</span>, short for
"half exponential" because the derivative at zero is one half instead of one,
but otherwise it looks like an exponential.</p>
<iframe src = "https://www.desmos.com/calculator/6qdzpcumvk?embed"
id = ""
class = "desmosiframe">
</iframe>
<p><span class="math">\[hex(x) := \frac{e^x  1}{x} = \sum_{k=0}^{\infty} \frac{x^k}{(k + 1)!}\]</span></p>
<p>Hex is well behaved at the origin, even with the division by zero, because the
division is in some sense just an artifact of writing the function down in a
<a href="https://en.wikipedia.org/wiki/Closedform_expression">Closed Form</a>. We can use
the sum representation to compute it around zero nicely. We can also see this
by using
<a href="https://en.wikipedia.org/wiki/L%27H%C3%B4pital%27s_rule">L'HÃ´pital's rule</a> to
compute the limit of the closed form of hex. Here is the resulting version of
<span class="math">\(\eqref{eqn:position_with_hex}\)</span> written in Dart.</p>
<pre><code class="languagedart">///
/// Return the value at a given time.
///
/// Time can be negative, positive, or zero, it should also be able to be
/// positive or negative infinity, but I haven't verified that Dart's exp
/// function correctly handles those cases.
///
double value(double time)
{
//
// This version of hex maintains about 14 digits of precision, not full
// machine precision (~16 digits for doubles).
//
double hex(double x)
{
//
// A threshold of 10^2 seems like a good compromise. The smaller
// the threshold is, the fewer terms we need to use to accurately
// evaluate hex. But smaller thresholds increase the loss of
// significance when using the exponential form below. The
// truncation error introduced by a threshold of 10^2 is O(x^6),
// or on the order of 1e12. In fact, the first term that we lose
// from the sum is x^6/6!, or 10^12/720, or 1.38e15, so our
// truncation error is closer to 1e15.
//
if (x.abs() < 1e2)
return 1 + (1 + (1 + (1 + x / 5) * x / 4) * x / 3) * x / 2;
//
// The worst case loss of significance from the subtraction below
// will be when x = 10^2.
//
// log2(1(1/e^(10^2))) ~ 6.6
//
// So we can expect to loose 7 bits of precision, from our doubles
// 53 bit mantissa. Or ~2 digits from our ~16 digits of precision.
//
return (exp(x)  1) / x;
}
return initial_value + initial_rate * time * hex(lambda * time);
}</code></pre>
<h2 id="lambda">Lambda</h2>
<p>We now have our solutions for <span class="math">\(\eqref{eqn:exponential_decay}\)</span> and
<span class="math">\(\eqref{eqn:position_diffeq}\)</span>, but we're still stuck specifying <span class="math">\(X_0\)</span>,
<span class="math">\(V_0\)</span>, <span class="math">\(\lambda\)</span>, and <span class="math">\(T\)</span> (the total time of the simulation). Instead,
we would like to be specifying <span class="math">\(X_0\)</span>, <span class="math">\(X_T\)</span>, <span class="math">\(V_T\)</span>, and <span class="math">\(T\)</span>, where</p>
<p><span class="math">\[
\begin{align*}
X_T &:= X(T)\\
V_T &:= V(T).
\end{align*}
\]</span></p>
<p>In other words, we need to come up with equations that give us <span class="math">\(V_0\)</span> and
<span class="math">\(\lambda\)</span> in terms of <span class="math">\(X_0\)</span>, <span class="math">\(X_T\)</span>, <span class="math">\(V_T\)</span>, and <span class="math">\(T\)</span>.</p>
<p>We can use <span class="math">\(\eqref{eqn:velocity}\)</span>, the solution for our velocity at a given
time, to compute <span class="math">\(\lambda\)</span> if we know <span class="math">\(V_0\)</span>, <span class="math">\(V_T\)</span>, and <span class="math">\(T\)</span>. This can
then be substituted into <span class="math">\(\eqref{eqn:position}\)</span> which gives us an equation
relating <span class="math">\(X_0\)</span>, <span class="math">\(X_T\)</span>, <span class="math">\(V_0\)</span>, <span class="math">\(V_T\)</span>, and <span class="math">\(T\)</span>. We can then solve that
equation for <span class="math">\(V_0\)</span>.</p>
<button dataopen = Hide derivation
dataclosed = Show derivation
class = "hiddenshortcodebutton">
Show derivation
</button>
</section>
<section class="content
hiddenshortcodewrapper
startclosed
">
<div class="hiddenshortcodecontent" style="overflow: auto">
<p>We want to solve <span class="math">\(\eqref{eqn:velocity}\)</span> for <span class="math">\(\lambda\)</span>, which we can do if
we can take the log of the exponential.</p>
<p><span class="math">\[V(t) = V_0 e^{\lambda t}\]</span></p>
<p>Divide both sides by <span class="math">\(V_0\)</span> and then take the log of both sides.</p>
<p><span class="math">\[log(\frac{V_T}{V_0}) = \lambda T\]</span></p>
<p>Divide both sides by <span class="math">\(T\)</span> to get our final equation for <span class="math">\(\lambda\)</span>.</p>
</div>
</section>
<section class="content">
<p><span class="math">\[
\begin{equation}\label{eqn:lambda}
\lambda = \frac{log(\frac{V_T}{V_0})}{T}
\end{equation}
\]</span></p>
<p>We will need to use this equation once we've solved <span class="math">\(\eqref{eqn:position}\)</span>
for <span class="math">\(V_0\)</span> to compute <span class="math">\(\lambda\)</span>. Again, we can write <span class="math">\(\eqref{eqn:lambda}\)</span>
in Dart.</p>
<pre><code class="languagedart">///
/// Compute the proportionality coefficient lambda given the start and end
/// rates as well as total time taken.
///
static double _lambda(double final_rate,
double initial_rate,
double total_time)
{
//
// If final_rate, or initial_rate is zero then the other must also be
// zero. This is because the only way to actually get to zero with an
// exponential is to already be there. And if you're there, there is
// no way to leave. In this case lambda should be zero, because our
// rate is not changing.
//
assert((final_rate == 0.0) == (initial_rate == 0.0));
if (final_rate == 0.0)
return 0.0;
//
// Lambda is not a complex number, we are only interested in solving
// for real values. So final_rate and initial_rate must also have the
// same sign.
//
assert((final_rate > 0.0) == (initial_rate > 0.0));
return log(final_rate / initial_rate) / total_time;
}</code></pre>
<p>We can now substitute <span class="math">\(\eqref{eqn:lambda}\)</span> into <span class="math">\(\eqref{eqn:position}\)</span>,
giving us an equation for position that is parameterized by <span class="math">\(X_0\)</span>, <span class="math">\(V_0\)</span>,
<span class="math">\(V_T\)</span>, and <span class="math">\(T\)</span>.</p>
<p><span class="math">\[
\begin{equation}\label{eqn:position_no_lambda}
X(t) = X_0 + \frac{T}{log(\frac{V_T}{V_0})}
(V_0 e^{\frac{log(\frac{V_T}{V_0})}{T} t}  V_0)
\end{equation}
\]</span></p>
<p>We can play with this function in Desmos as well, but we still don't get to
specify the final position of the animation (<span class="math">\(X_T\)</span>).</p>
<iframe src = "https://www.desmos.com/calculator/thwcw9lw0q?embed"
id = ""
class = "desmosiframe">
</iframe>
<p>You'll probably notice that <span class="math">\(V_0\)</span> and <span class="math">\(V_T\)</span> have to have the same sign. If
they do not then desmos doesn't show a graph at all. This is because
<span class="math">\(\eqref{eqn:lambda}\)</span> takes the logarithm of their ratio, and as long as
<span class="math">\(V_0\)</span> and <span class="math">\(V_T\)</span> have the same sign their ratio is positive. The logarithm
for real numbers is not defined for negative numbers. So Desmos (and the Dart
implementation above) give up. But if we were to use the complex exponential
and logarithm then there is actually a solution when <span class="math">\(V_0\)</span> and <span class="math">\(V_T\)</span> have
different signs. The solution ends up being a combination of sine, cosine and
exponential functions. The sine and cosine allow for the change in sign of the
rate. I touched on this briefly at the end of my
<a href="//socialhacker.com/posts/2d_rotation/#exponentialmap">2D Rotation</a> post. It is
never the case in the game I'm writing that I want the initial and final
velocities to have different signs, so I opted to keep the solution real. I
could imagine an explosion animation that contracts at the end, but that wasn't
what I was going for visually.</p>
<h2 id="initialvelocity">Initial Velocity</h2>
<p>We now have <span class="math">\(\eqref{eqn:position}\)</span> that tells us <span class="math">\(X_T\)</span> given <span class="math">\(X_0\)</span>,
<span class="math">\(V_0\)</span>, <span class="math">\(\lambda\)</span>, and <span class="math">\(T\)</span>. And we just found <span class="math">\(\eqref{eqn:lambda}\)</span>, an
equation for <span class="math">\(\lambda\)</span>. Then we substituted <span class="math">\(\eqref{eqn:lambda}\)</span> into
<span class="math">\(\eqref{eqn:position}\)</span> to get <span class="math">\(\eqref{eqn:position_no_lambda}\)</span>. Now we'll
solve the result for <span class="math">\(V_0\)</span>. This is where the math got interesting; I had
never encountered the
<a href="https://en.wikipedia.org/wiki/Lambert_W_function">Lambert W function</a> before.
And it turns out that solving for <span class="math">\(V_0\)</span> will need it. To apply it we need to
get one side of this equation to look like <span class="math">\(f(V_0) e^{f(V_0)}\)</span>, and the other
side to not have <span class="math">\(V_0\)</span> in it. Because it will make the remaining math easier
to follow I'm going define <span class="math">\(\Delta X\)</span> here.</p>
<p><span class="math">\[\Delta X := X_T  X_0\]</span></p>
<button dataopen = Hide derivation
dataclosed = Show derivation
class = "hiddenshortcodebutton">
Show derivation
</button>
</section>
<section class="content
hiddenshortcodewrapper
startclosed
">
<div class="hiddenshortcodecontent" style="overflow: auto">
<p>If we evaluate <span class="math">\(\eqref{eqn:position_no_lambda}\)</span> at <span class="math">\(T\)</span>, our final time,
we will have an equation that relates <span class="math">\(X_0\)</span>, <span class="math">\(X_T\)</span>, <span class="math">\(V_0\)</span>, <span class="math">\(V_T\)</span>, and
<span class="math">\(T\)</span>. With the addition of <span class="math">\(\Delta X\)</span> the result looks like</p>
<p><span class="math">\[
\Delta X = \frac{T}{log(\frac{V_T}{V_0})}
(V_0 e^{\frac{log(\frac{V_T}{V_0})}{T} T}  V_0).
\]</span></p>
<p>We can immediately cancel the two <span class="math">\(T\)</span> factors in the exponent and then
simplify the exponent of the log of <span class="math">\(V_T\)</span> divided by <span class="math">\(V_0\)</span>, and finally
cancel the <span class="math">\(V_0\)</span> factors. The result is that the first term in the
parentheses just becomes <span class="math">\(V_T\)</span>. This makes sense given the substitution I
considered in <span class="math">\(\eqref{eqn:position_from_rate}\)</span>.</p>
<p><span class="math">\[
\Delta X = \frac{T}{log(\frac{V_T}{V_0})}(V_T  V_0)
\]</span></p>
<p>Multiply both sides by <span class="math">\(log(V_T)  log(V_0) = log(\frac{V_T}{V_0})\)</span>.</p>
<p><span class="math">\[\Delta X log(V_T)  \Delta X log(V_0) = V_T T  V_0 T\]</span></p>
<p>Divide by <span class="math">\(\Delta X\)</span> and move all the terms with <span class="math">\(V_0\)</span> to one side, and
all the remaining terms (those with <span class="math">\(V_T\)</span>) to the other side.</p>
<p><span class="math">\[
log(V_T)  T\frac{V_T}{\Delta X} =
log(V_0)  T\frac{V_0}{\Delta X}
\]</span></p>
<p>We're getting close; exponentiate each side.</p>
<p><span class="math">\[
V_T e^{T\frac{V_T}{\Delta X}} =
V_0 e^{T\frac{V_0}{\Delta X}}
\]</span></p>
<p>Now all we need to do is make the right hand side look like
<span class="math">\(f(V_0) e^{f(V_0)}\)</span>. We can do that by multiplying both sides by
<span class="math">\(\frac{T}{\Delta X}\)</span>.</p>
</div>
</section>
<section class="content">
<p>We now have an equation that relates all of our coefficients (<span class="math">\(X_0, X_T, V_0,
V_T\)</span>, and <span class="math">\(T\)</span>); We just have to solve it for <span class="math">\(V_0\)</span>.</p>
<p><span class="math">\[
\begin{equation}\label{eqn:initial_velocity_symetric}
T \frac{V_T}{\Delta X} e^{T \frac{V_T}{\Delta X}} =
T \frac{V_0}{\Delta X} e^{T \frac{V_0}{\Delta X}}
\end{equation}
\]</span></p>
<p>Now that the right hand side is in the correct form
<span class="math">\(f(V_0) = T \frac{V_0}{\Delta X}\)</span>, we can apply W to both sides. You might
notice that the left hand side is also in the same form, it is
<span class="math">\(f(V_T) = T \frac{V_T}{\Delta X}\)</span>. More about that later.</p>
<p><span class="math">\[
W(T \frac{V_T}{\Delta X} e^{T \frac{V_T}{\Delta X}}) =
T \frac{V_0}{\Delta X}
\]</span></p>
<p>And finally, multiply both sides by <span class="math">\(\frac{\Delta X}{T}\)</span> to solve for
<span class="math">\(V_0\)</span>.</p>
<p><span class="math">\[
V_0 = W(T \frac{V_T}{\Delta X} e^{T \frac{V_T}{\Delta X}})
\frac{\Delta X}{T}
\]</span></p>
<p>This is a lot to look at, but it has some repetition that we can factor out,
making it easier to understand; substitute <span class="math">\(A = T \frac{V_T}{\Delta X}\)</span>.</p>
<p><span class="math">\[
\begin{equation}\label{eqn:initial_velocity}
V_0 = V_T \frac{W(A e^A)}{A}
\end{equation}
\]</span></p>
<p>I wanted to add a Desmos graph here where you could play with the new set of
parameters, but Desmos doesn't currently support the Lambert W function, which
makes it pretty hard to evaluate the above equation. It could be approximated
with a lot of work, but this post has taken long enough to write already.</p>
<p>But we can get an idea for the sort of solutions that the Lambert W function
would return. Below is a graph of <span class="math">\(f(x) = xe^x\)</span> that shows that for any value
of <span class="math">\(x_1 < 0\)</span> other than <span class="math">\(x_1 = 1\)</span> there is another value <span class="math">\(x_2 \neq x_1\)</span>
such that <span class="math">\(f(x_1) = f(x_2)\)</span>. In other words, if <span class="math">\(x\)</span> is less than zero, and
not equal to negative one, then the inverse of <span class="math">\(f(x)\)</span> has two values. That
other value can be computed using one of the two branches of the Lambert W
function.</p>
<iframe src = "https://www.desmos.com/calculator/obnlc5a5un?embed"
id = ""
class = "desmosiframe">
</iframe>
<p>I'd like to return briefly to the interesting symmetry of
<span class="math">\(\eqref{eqn:initial_velocity_symetric}\)</span>, it was of the form:</p>
<p><span class="math">\[X e^X = Y e^Y\]</span></p>
<p>where</p>
<p><span class="math">\[
\begin{align*}
X &:= f(V_T) = T \frac{V_T}{\Delta X}\\
Y &:= f(V_0) = T \frac{V_0}{\Delta X}.
\end{align*}
\]</span></p>
<p>Our problem was that we were given <span class="math">\(Y\)</span> and we needed to compute <span class="math">\(X\)</span>, more
or less. It's probably obvious that there's a trivial solution to this
problem; <span class="math">\(X = Y\)</span>. That makes both sides identical, and so obviously
it's a solution to <span class="math">\(\eqref{eqn:initial_velocity_symetric}\)</span>, but we arrived at
<span class="math">\(\eqref{eqn:initial_velocity_symetric}\)</span> by manipulating
<span class="math">\(\eqref{eqn:position}\)</span>. And <span class="math">\(\eqref{eqn:position}\)</span> is not valid when
<span class="math">\(V_T = V_0\)</span> (because then <span class="math">\(\lambda\)</span> is zero), and since <span class="math">\(X\)</span> and <span class="math">\(Y\)</span> are
just <span class="math">\(f(V_T)\)</span> and <span class="math">\(f(V_0)\)</span>, <span class="math">\(X = Y\)</span> can't be a solution we're actually
looking for. Fortunately, there is a second solution for all values of <span class="math">\(A\)</span>
other than <span class="math">\(1\)</span>. When <span class="math">\(A = 1\)</span> the initial rate is just the final rate.</p>
<pre><code class="languagedart">///
/// Return the initial rate that will result in the given change in value
/// and rate, over the specified total time.
///
/// delta_value in [ 0 .. infinity)
/// final_rate in (infinity .. infinity)
/// total_time in [ 0 .. infinity)
///
static double _initial_rate(double delta_value,
double final_rate,
double total_time)
{
///
/// If delta_value is zero, then final_rate must also be zero. It is
/// not possible to have zero change in value with a nonzero
/// final_rate because the exponential is monotonic.
///
assert(delta_value != 0.0  final_rate == 0.0);
///
/// Since we're not expected to change the value at all, and final_rate
/// is zero, _initial_rate should also be zero.
///
if (delta_value == 0.0)
return 0.0;
///
/// If total_time is zero, then delta_value must also be zero. If
/// delta_value were not zero we would have to somehow give two
/// different values for the same instant in time.
///
assert(total_time != 0.0  delta_value == 0.0);
///
/// If total_time is zero then _initial_rate will match final_rate.
///
if (total_time == 0.0)
return final_rate;
final double A = total_time * final_rate / delta_value;
if (A > 1.0)
return W_negative_one(A * exp(A)) * final_rate / A;
if (A < 1.0)
return W_zero(A * exp(A)) * final_rate / A;
return final_rate;
}</code></pre>
<p>To evaluate the Lambert W function I wrote a version of the approximations found
in <a href="https://arxiv.org/abs/1003.1628">Having Fun with Lambert W(x) Function</a>. A
post about that implementation might be a good idea. For now, the source can
be found <a href="//socialhacker.com/source/breaker/web/lambert_w_function_source/">here</a>.</p>
<h2 id="dimensionalanalysis">Dimensional Analysis</h2>
<p>It's a good idea to double check our work and make sure that the resulting
equations make sense from a units perspective. Let's add units. First we'll
figure out the units of <span class="math">\(\lambda\)</span>. We start with <span class="math">\(\eqref{eqn:lambda}\)</span> and
add units to the right side.</p>
<p><span class="math">\[
\lambda = \frac{log(\frac{V(t) \si{m s^{1}}}{V_0 \si{m s^{1}}})}{t \si{s}}
\]</span></p>
<p>The units of velocity (<span class="math">\(\si{m s^{1}}\)</span>) cancel, leaving the numerator
unitless. The denominator still has units of seconds, so lambda has units
of inverse seconds, also known as Hertz, a unit of frequency.</p>
<p>The units for <span class="math">\(\eqref{eqn:velocity}\)</span> are also simple.</p>
<p><span class="math">\[V(t) = V_0 \si{m s^{1}} e^{\lambda \si{s^{1}} t \si{s}}\]</span></p>
<p>The units of <span class="math">\(\lambda\)</span> and <span class="math">\(t\)</span> in the exponential cancel, leaving that
unitless. The only remaining units are from <span class="math">\(V_0\)</span>, so <span class="math">\(V(t)\)</span> has the same
units, those of velocity.</p>
<p>Next we can check the units for <span class="math">\(\eqref{eqn:position_from_rate}\)</span>.</p>
<p><span class="math">\[
X(t) \si{m}  X_0 \si{m} =
\frac{1}{\lambda \si{s^{1}}}
(V(t) \si{m s^{1}}  V_0\si{m s^{1}})
\]</span></p>
<p>We can cancel <span class="math">\(\si{s^{1}}\)</span> from numerator and denominator, leaving meters
on both sides, giving the correct units for position.</p>
<p>Finally let's check <span class="math">\(\eqref{eqn:initial_velocity}\)</span>  to do that we just have
to show that <span class="math">\(A(t)\)</span> is unitless.</p>
<p><span class="math">\[A(t) = t \si{s} \frac{V(t) \si{m s^{1}}}{X(t) \si{m}}\]</span></p>
<p>Pretty easy to see that seconds and meters cancel out completely.</p>
<div class="footnotes">
<hr>
<ol>
<li id="fn:1"><p>Why Dart? you're probably asking right now. Well, I wanted to write a web
game, and I got about one git commit into doing it in Javascript when I
remembered that Javascript doesn't have operator overloading. For me,
operator overloading is a language requirement; without it you just can't
write much math beyond scalar algebra. I also like that Dart has some
static typing abilities. I know that operator overloading, as well as
static vs. dynamic typing, are contentious topics for a lot of people, but
I'm not going to say much more about them in this post, perhaps later. I
will say that I'm very much looking forward to using something compiled to
WebAssembly instead.</p>
<a class="footnotereturn" href="#fnref:1"><sup>[return]</sup></a></li>
<li id="fn:2"><p>My brother in law, <a href="http://home.sandiego.edu/~shulman/">Michael Shulman</a>,
pointed out that what I've called the Hexponential can also be viewed as
the <a href="https://en.wikipedia.org/wiki/Difference_quotient">Difference Quotient</a>
of <span class="math">\(e^x\)</span> at zero. And that the general operation on an infinite series
of subtracting the first term and dividing by the argument produces a
difference quotient for the function at zero.</p>
<a class="footnotereturn" href="#fnref:2"><sup>[return]</sup></a></li>
</ol>
</div>

2D Rotation
//socialhacker.com/posts/2d_rotation/
Thu, 05 Sep 2013 21:55:00 0800
anton@socialhacker.com (Anton Staaf)
//socialhacker.com/posts/2d_rotation/
<p>I'm hoping with this post to show one way that complex numbers come about and
how they are a natural way of representing rotations in 2D. To do this I will
introduce a small amount of Clifford algebra and some infinite series
expansions. A benefit of understanding rotations in this way will be that it
generalizes to arbitrary dimensions, though you probably only care about the
two and three dimensional cases.</p>
<p>A friend of mine recently asked me about 2D rotations. He had started with a
<a href="http://en.wikipedia.org/wiki/Rotation_matrix">2x2 rotation matrix</a>:</p>
<p><span class="math">\[
\left( \begin{array}{cr}
cos(\theta) & sin(\theta)\\
sin(\theta) & cos(\theta)\\
\end{array} \right)
\left( \begin{array}{c} x\\ y\\ \end{array} \right) =
\left( \begin{array}{c}
cos(\theta) x  sin(\theta) y\\
sin(\theta) x + cos(\theta) y\\
\end{array} \right)
\]</span></p>
<p>After playing with it for a while he concluded that the second row of the
matrix was redundant and you could just store the first row, or really any
row or column. This reminded him of something I had said a while back about
using complex numbers to represent rotations. This prompted me to write a
first version of this post as an email in response. Then he wrote again
saying that it seemed like the two component thing was the result of
<span class="math">\(e^{i\theta}\)</span>. So I have added a section on the exponential map and Taylor
series.</p>
<h2 id="complexnumbers">Complex Numbers</h2>
<p>First let's start with a bit of a review of complex numbers.
You've probably been introduced to them at some point as a
number with two components, a real portion and an imaginary
portion, where the imaginary portion is signified by having
a lower case <span class="math">\(i\)</span> associated with it.</p>
<p><span class="math">\[(a + b i)\]</span></p>
<p>And they were probably being used to fill in a gap when
someone tried to take the square root of a negative number.
Probably it was right around when you learned the quadratic
formula. Some people are introduced to complex numbers when
they start playing with fractals; the Mandelbrot set, Julia
sets, and others are defined in the complex plane. The
complex plane is what you get if you treat the real and
imaginary parts of a complex number as the <span class="math">\(x\)</span> and <span class="math">\(y\)</span>
components of a 2D vector. A lot of neat results come from
that mapping. Later I'll show a different way to associate
the components of a complex number with the <span class="math">\(x\)</span> and <span class="math">\(y\)</span>
components of a 2D vector, but first, let's remember what
happens when you multiply two complex numbers together.</p>
<p><span class="math">\[(a_1 + b_1 i) (a_2 + b_2 i)\]</span></p>
<p>You probably remember FOIL (First Outer Inner Last) which
tells you how to go about doing this multiplication. First
multiple the a's together, then the outer elements <span class="math">\((a_1
\text{and} b_2 i)\)</span>, then the inner elements <span class="math">\((b_1 i
\text{and} a_2)\)</span>, and finally the last elements, the b's.</p>
<p><span class="math">\[(a_1 a_2) + (a_1 b_2 i) + (b_1 i a_2) + (b_1 i b_2 i)\]</span></p>
<p>With complex numbers we're free to move the i's around inside
each product, so we'll move them to the end of each one, and
outside of the parentheses.</p>
<p><span class="math">\[(a_1 a_2) + (a_1 b_2) i + (b_1 a_2) i + (b_1 b_2) i i\]</span></p>
<p>The <span class="math">\(i i\)</span> that we get from the multiplication of the two
imaginary components <span class="math">\((b_1 \text{and} b_2)\)</span> of the two
complex numbers could also be written <span class="math">\(i^2\)</span>. The whole
reason for inventing <span class="math">\(i\)</span> was to provide an answer to the
question of what <span class="math">\(x\)</span> is in the following.</p>
<p><span class="math">\[x = \sqrt{1}\]</span></p>
<p>So, <span class="math">\(i^2 = 1\)</span>, and thus the result of multiplying two
imaginary components of a complex number together is a real
number, just one that has the opposite sign than it would
otherwise. So, taking this into account and merging the two
terms in the middle that each have a single <span class="math">\(i\)</span> in them we
can simplify the result of multiplying two complex numbers
down to the following.</p>
<p><span class="math">\[(a_1 a_2) + (a_1 b_2 + b_1 a_2) i  (b_1 b_2)\]</span></p>
<p>Finally, moving the imaginary portion to the end we get:</p>
<p><span class="math">\[(a_1 a_2  b_1 b_2) + (a_1 b_2 + b_1 a_2) i\]</span></p>
<p>Which is another complex number <span class="math">\((a_3 + b_3 i)\)</span> where
<span class="math">\(a_3\)</span> and <span class="math">\(b_3\)</span> are defined as:</p>
<p><span class="math">\[\begin{align*}
a_3 &= a_1 a_2  b_1 b_2 \\
b_3 &= a_1 b_2 + b_1 b_2
\end{align*}\]</span></p>
<p>With that basic review of complex numbers, let's move on to
talk about the Clifford algebra.</p>
<h2 id="cliffordalgebra">Clifford Algebra</h2>
<p>Above we had said that you could make a 2D plane by
associating the real and imaginary components of a complex
number with the <span class="math">\(x\)</span> and <span class="math">\(y\)</span> elements of a 2D vector.
But we didn't really talk about what that meant or how you
could distinguish an <span class="math">\(x\)</span> component from a <span class="math">\(y\)</span> component.
There has been an enormous amount written about this
subject, and I highly recommend Geometrical Vectors by
Gabriel Weinreich. But for now, I'm going to introduce two
new things, sort of like <span class="math">\(i\)</span> from the complex numbers,
called <span class="math">\(\mathbf{e_1}\)</span> and <span class="math">\(\mathbf{e_2}\)</span>. And we will
use them to distinguish between the two components of a 2D
vector. So, our vectors will look like this.
<span class="math">\((x \mathbf{e_1} + y \mathbf{e_2})\)</span>
These things, we'll call them bases, have a few properties:
a base times itself equals one, and swapping the position of
two bases in a term negates the term.</p>
<p><span class="math">\[
\mathbf{e_i e_i} = 1\\
\mathbf{e_i e_j} =  \mathbf{e_j e_i}
\]</span></p>
<p>These vectors behave just like you would expect a vector to
behave. You can add and subtract them.</p>
<p><span class="math">\[
(x_1 \mathbf{e_1} + y_1 \mathbf{e_2}) +
(x_2 \mathbf{e_1} + y_2 \mathbf{e_2}) =
((x_1 + x_2) \mathbf{e_1} + (y_1 + y_2) \mathbf{e_2})
\]</span></p>
<p>And you can multiply them by scalars.</p>
<p><span class="math">\[
c (x_1 \mathbf{e_1} + y_1 \mathbf{e_2}) =
(c x_1 \mathbf{e_1} + c y_1 \mathbf{e_2})
\]</span></p>
<p>But they also have another interesting trick, if we multiply
two of these vectors together we get an interesting new
object.</p>
<p><span class="math">\[(x_1 \mathbf{e_1} +
y_1 \mathbf{e_2})
(x_2 \mathbf{e_1} +
y_2 \mathbf{e_2})\]</span></p>
<p>using FOIL you get</p>
<p><span class="math">\[(x_1 x_2) \mathbf{e_1 e_1} +
(x_1 y_2) \mathbf{e_1 e_2} +
(y_1 x_2) \mathbf{e_2 e_1} +
(y_1 y_2) \mathbf{e_2 e_2}\]</span></p>
<p>Since <span class="math">\(\mathbf{e_1 e_1} = 1\)</span> and <span class="math">\(\mathbf{e_2 e_2} = 1\)</span>
the first and last terms turn into scalars and you get</p>
<p><span class="math">\[(x_1 x_2) +
(x_1 y_2) \mathbf{e_1 e_2} +
(y_1 x_2) \mathbf{e_2 e_1} +
(y_1 y_2)\]</span></p>
<p>Now, the middle two terms can be combined by swapping the
<span class="math">\(\mathbf{e_2 e_1}\)</span> in the second term to be <span class="math">\(\mathbf{e_1
e_2}\)</span> and negating the whole term. So the result is</p>
<p><span class="math">\[(x_1 x_2) +
(x_1 y_2  y_1 x_2) \mathbf{e_1 e_2} +
(y_1 y_2)\]</span></p>
<p>Finally, grouping the first and last term together you get</p>
<p><span class="math">\[(x_1 x_2 + y_1 y_2) +
(x_1 y_2  y_1 x_2) \mathbf{e_1 e_2}\]</span></p>
<p>We see that the first term is just the dot product of the
two vectors, and the second term is just the 2D cross
product <sup class="footnoteref" id="fnref:1"><a class="footnote" href="#fn:1">1</a></sup> times something
weird, this <span class="math">\(\mathbf{e_1 e_2}\)</span> term. So we've got some
new odd object here: a scalar plus a scalar times a strange
pair of bases. If we replace the dot and cross product
values with the letters <span class="math">\(a\)</span> and <span class="math">\(b\)</span> we have <span class="math">\(a + b
\mathbf{e_1 e_2}\)</span>.</p>
<p>As you may know, the dot product of two vectors is equal to
the cosine of the angle between them times the length of
each vector. Similarly, the length of the cross product of
two vectors is equal to the sine of the angle between them
times the length of each vector. These sines and cosines
allow us to get back to rotation.</p>
<h2 id="2drotationrevisited">2D Rotation Revisited</h2>
<p>Now what happens if we multiply one of our original vectors
times one of these?</p>
<p><span class="math">\[(x \mathbf{e_1} + y \mathbf{e_2}) (a + b \mathbf{e_1 e_2})\]</span></p>
<p>We get:</p>
<p><span class="math">\[(a x) \mathbf{e_1} +
(b x) \mathbf{e_1 e_1 e_2} +
(a y) \mathbf{e_2} +
(b y) \mathbf{e_2 e_1 e_2}\]</span></p>
<p>Which after simplification is:</p>
<p><span class="math">\[(a x  b y) \mathbf{e_1} + (b x + a y) \mathbf{e_2}\]</span></p>
<p>Which looks a lot like a rotation matrix application. <sup class="footnoteref" id="fnref:2"><a class="footnote" href="#fn:2">2</a></sup> Especially when you
remember that if the two vectors we started with are unit length then
a and b are equal to the cos and sin of the angles between
the two vectors. In which case we have:</p>
<p><span class="math">\[a = cos(\theta)\\
b = sin(\theta)\]</span></p>
<p>and after substitution:</p>
<p><span class="math">\[
\begin{align*}
&(cos(\theta) x  sin(\theta) y) \mathbf{e_1} +\\
&(sin(\theta) x + cos(\theta) y) \mathbf{e_2}
\end{align*}
\]</span></p>
<h2 id="complexnumbersrevisited">Complex Numbers Revisited</h2>
<p>You can probably see where this is going. Let's try
multiplying two of these 'scalar plus scalar times base pairs'
together.</p>
<p><span class="math">\[
(a_1 + b_1 \mathbf{e_1 e_2}) (a_2 + b_2 \mathbf{e_1 e_2})
\]</span></p>
<p>Again, using FOIL we get:</p>
<p><span class="math">\[
(a_1 a_2) +
(a_1 b_2) \mathbf{e_1 e_2} +
b_1 \mathbf{e_1 e_2} a_2 +
b_1 \mathbf{e_1 e_2} b_2 \mathbf{e_1 e_2}
\]</span></p>
<p>It is fine to move the scalars around, so let's clean this up:</p>
<p><span class="math">\[
(a_1 a_2) +
(a_1 b_2) \mathbf{e_1 e_2} +
(a_2 b_1) \mathbf{e_1 e_2} +
(b_1 b_2) \mathbf{e_1 e_2 e_1 e_2}
\]</span></p>
<p>We can combine the two <span class="math">\(\mathbf{e_1 e_2}\)</span> terms:</p>
<p><span class="math">\[
(a_1 a_2) +
(a_1 b_2 + a_2 b_1) \mathbf{e_1 e_2} +
(b_1 b_2) \mathbf{e_1 e_2 e_1 e_2}
\]</span></p>
<p>Next we deal with the <span class="math">\(\mathbf{e_1 e_2 e_1 e_2}\)</span> term. If
we swap the middle <span class="math">\(\mathbf{e_2 e_1}\)</span> into <span class="math">\(\mathbf{e_1
e_2}\)</span> and negate the whole thing we get <span class="math">\(\mathbf{e_1 e_1
e_2 e_2}\)</span>. And since a base times itself is <span class="math">\(1\)</span> we have
<span class="math">\(1 * 1\)</span> or <span class="math">\(1\)</span>. So, the last term can be replaced
with <span class="math">\((b_1 b_2)\)</span>, causing the entire thing to turn
into:</p>
<p><span class="math">\[
\begin{align*}
&(a_1 a_2  b_1 b_2) +\\
&(a_1 b_2 + a_2 b_1) \mathbf{e_1 e_2}
\end{align*}
\]</span></p>
<p>And poof, we have another one of these scalar plus scalar
times <span class="math">\(\mathbf{e_1 e_2}\)</span> things. The fact that
<span class="math">\(\mathbf{e_1 e_2 e_1 e_2} = 1\)</span> should have given it away:
<span class="math">\(\mathbf{e_1 e_2}\)</span> could also be called <span class="math">\(i\)</span> and these
are complex numbers (or at least they behave like them,
which in some sense means that they are them).</p>
<p>If complex numbers really do represent rotations in 2D then
we would expect that there would be a way to combine two
rotations that are represented by complex numbers, resulting
in a single complex number that represents the combined
rotation. And you are probably not surprised to learn that
there is, and it is just complex multiplication (which we
worked out above). To show this let's assume that <span class="math">\((a_1 +
b_1 \mathbf{e_1 e_2})\)</span> represents a rotation by <span class="math">\(\theta\)</span>
radians and <span class="math">\((a_2 + b_2 \mathbf{e_1 e_2})\)</span> represents a
rotation by <span class="math">\(\phi\)</span> radians. So:</p>
<p><span class="math">\[
a_1 = cos(\theta)\\
b_1 = sin(\theta)\\
a_2 = cos(\phi)\\
b_2 = sin(\phi)
\]</span></p>
<p>If we rewrite the result of multiplying two complex numbers
together and substitute these cosines and sines in we get:</p>
<p><span class="math">\[
\begin{align*}
&(cos(\theta) cos(\phi)  sin(\theta) sin(\phi)) +\\
&(cos(\theta) sin(\phi) + cos(\phi) sin(\theta))
\mathbf{e_1 e_2}
\end{align*}
\]</span></p>
<p>Now we have to remember (or rederive, but this post is
getting too long as it is) the sin and cos of the sum of
angles formulas. They are, probably not surprisingly:</p>
<p><span class="math">\[
\begin{align*}
cos(\theta + \phi) &=
cos(\theta) cos(\phi)  sin(\theta) sin(\phi)\\
sin(\theta + \phi) &=
cos(\theta) sin(\phi) + cos(\phi) sin(\theta)\\
\end{align*}
\]</span></p>
<p>And thus, we can rewrite the product of two complex numbers
that represent rotations as:</p>
<p><span class="math">\[cos(\theta + \phi) + sin(\theta + \phi) \mathbf{e_1 e_2}\]</span></p>
<p>And indeed, the product of two complex numbers that
represent rotations, is itself a rotation, one that is the
sum of the two independent rotations.</p>
<h2 id="exponentialmap">Exponential Map</h2>
<p>The exponential map is a special function that is its own
derivative. It is fascinating, and I recommend reading more
about it. Here I'm just going to quickly show one fantastic
result. I'll need to use the words Taylor Series and
infinity, but I'm not going to justify them much. It can be
thought of as an infinite sum of terms, or as the
exponentiation <span class="math">\(e^x\)</span>.</p>
<p><span class="math">\[exp(x) = e^x = \sum_{k=0}^{\infty} \frac{x^k}{k!}\]</span></p>
<p>This function is valid for all complex numbers, but we will
limit the input to just the imaginary numbers (the imaginary
portion of a complex number). To make the notation a little simpler I'll use <span class="math">\(i\)</span>
instead of <span class="math">\(\mathbf{e_1 e_2}\)</span>. I'll show that by doing
this we effectively map an infinite line to the circle of radius
one centered at the origin of the complex plane. Points on the line
can be thought of as representing angles in radians. And every time
we move <span class="math">\(2 \pi\)</span> along the line we make one full loop around the
circle. So, there are many points on the line that map to the same
point on the circle. These all represent the same rotation.</p>
<p><span class="math">\[exp(x i) = e^{x i} = \sum_{k=0}^{\infty} \frac{(x i)^k}{k!}\]</span></p>
<p>First, let's look at the <span class="math">\((x i)^k\)</span> term. The first few
terms in the infinite sum and the generalization for an
arbitrary value of <span class="math">\(k\)</span> are:</p>
<p><span class="math">\[
\begin{align*}
(x i)^0 &= x^0 = 1\\
(x i)^1 &= x^1 i = x i\\
(x i)^2 &= x^2 i i = 1 x^2\\
(x i)^3 &= x^3 i i i = 1 x^3 i\\
&\vdots\\
(x i)^k &=
x^k i^k =
\begin{cases}
1^{\frac{k}{2}} x^k & k\;\text{is even}
\\[1ex]
1^{\frac{k1}{2}} x^k i & k\;\text{is odd}
\end{cases}\\
\end{align*}
\]</span></p>
<p>If we group all of the even and all of the odd terms
together we get:</p>
<p><span class="math">\[
e^{x i} =
\sum_{k=0,2,4...}^{\infty} \frac{1^{\frac{k}{2}} x^k}{k!} +
\sum_{k=1,3,5...}^{\infty} \frac{1^{\frac{k1}{2}} x^k}{k!}i
\]</span></p>
<p>We can turn the sums back into simple sums from zero to
infinity by transforming <span class="math">\(k\)</span> in each of them. In the
first one we can replace <span class="math">\(k\)</span> with <span class="math">\(2k\)</span>, and in the
second we can replace <span class="math">\(k\)</span> with <span class="math">\(2k+1\)</span>. The result is:</p>
<p><span class="math">\[
e^{x i} =
\sum_{k=0}^{\infty} \frac{1^k x^{2k}}{(2k)!} +
\sum_{k=0}^{\infty} \frac{1^k x^{2k+1}}{(2k+1)!}i
\]</span></p>
<p>It turns out that the first sum is actually the Taylor
series expansion for <span class="math">\(cos(x)\)</span> and the second sum is the
Taylor series expansion for <span class="math">\(sin(x)\)</span>. So this can be
rewritten as:</p>
<p><span class="math">\[ e^{x i} = cos(x) + sin(x) i \]</span></p>
<p>This beautiful result is known as <a href="http://en.wikipedia.org/wiki/Euler's_formula">Euler's formula</a>.</p>
<h2 id="furtherreading">Further Reading</h2>
<ul>
<li><a href="https://en.wikipedia.org/wiki/Universal_geometric_algebra">Universal Geometric Algebra</a></li>
</ul>
<div class="footnotes">
<hr>
<ol>
<li id="fn:1"><p>In 2D the cross product as we normally think of it doesn't
exist, but the value above can be thought of as the Z
component of a 3D cross product of two vectors that lie in
the XY plane. Since the two vectors have zero Z
components, the X and Y components of their cross product
is zero, so the overall cross product length is just the
length of the Z portion.</p>
<a class="footnotereturn" href="#fnref:1"><sup>[return]</sup></a></li>
<li id="fn:2"><p>There is a bit more subtlety to this, the actual group
action we care about is ATA* <sup class="footnoteref" id="fnref:3"><a class="footnote" href="#fn:3">3</a></sup> where A is a complex
number, T is a vector and A* is the conjugate of the
complex number. That action works even if the complex
number isn't unit, and it generalizes up to higher
dimensions (TA, what we did here, doesn't).</p>
<a class="footnotereturn" href="#fnref:2"><sup>[return]</sup></a></li>
<li id="fn:3"><p>The construction of a complex number as a multiplication
of two vectors using the odd base combination rules gives
a cool way to ask for a rotation between two vectors. If
you use the full ATA* group operation the rotation is
twice the angle between the two vectors though. This
turns out to be important in higher dimensions.</p>
<a class="footnotereturn" href="#fnref:3"><sup>[return]</sup></a></li>
</ol>
</div>

Mandelbrot
//socialhacker.com/posts/fractals/mandelbrot/
Wed, 16 May 2012 00:00:00 +0000
anton@socialhacker.com (Anton Staaf)
//socialhacker.com/posts/fractals/mandelbrot/
<p><a href="//socialhacker.com/applications/mandelbrot/mandelbrot.html">Mandelbrot</a> is a javascript
implementation of a simple mandelbrot set calculator.</p>
<p></p>
<pre><code class="languagejavascript">//
// Set the pixel at location <x,y> in the image data to <r,g,b,a>. The r, g,
// and b elements are the red, green, and blue color components. The a element
// is the alpha, or transparency value. The r, g, b, and a values can range
// from 0 to 255.
//
function set_pixel(image_data, x, y, r, g, b, a)
{
// Compute the index into the pixel data. Each pixel is represented by four
// sequential values in the image_data.data array.
index = (x + y * image_data.width) * 4;
image_data.data[index + 0] = r;
image_data.data[index + 1] = g;
image_data.data[index + 2] = b;
image_data.data[index + 3] = a;
}
//
// Compute the number of iterations required for a single orbit of the
// mandelbrot equation to escape from a circle of radius 2 centered at the
// origin of the complex plane.
//
function compute_escape_time(c_r, c_i, maximum_iterations)
{
z_r = 0.0;
z_i = 0.0;
for (i = 0; i < maximum_iterations; i++)
{
//
// Compute a single iteration of Z^2 + C. Complex numbers are of the
// form "real + imaginary * i", so to square them you end up computing:
//
// (real + imaginary * i) * (real + imaginary * i)
// =
// real * real + imaginary * imaginary * i^2 + 2 * real * imaginary * i
// =
// real * real  imaginary * imaginary + 2 * real * imaginary * i
//
// So the new real value is (real * real  imaginary * imaginary)
// And the new imaginary value is (2 * real * imaginary)
//
// The reason the first + turns into a  is because i^2 is defined to be
// equal to 1, that's what makes the numbers imaginary.
//
temp = (z_r * z_r)  (z_i * z_i) + c_r;
z_i = (2.0 * z_r * z_i) + c_i;
z_r = temp;
// Check to see if the magnitude of the complex number is larger than
// 2. We check whether the squared magnitude is greater than 4 here to
// avoid taking a square root, because square roots are slow.
if (((z_r * z_r) + (z_i * z_i)) > 4.0)
return i;
}
// Return the maximum iterations value if we never escaped.
return maximum_iterations;
}
//
// Draw a Mandelbrot set filling in a canvas specified by element_id.
//
function draw_mandelbrot(element_id)
{
// Lookup the canvas and get a 2D rendering context from it.
element = document.getElementById(element_id);
context = element.getContext("2d");
//
// Construct an image data object to hold the pixels before they are
// drawn to the screen.
//
image_data = context.createImageData(element.width,
element.height);
//
// Iterate over every pixel in the canvas and compute the escape time for
// the corresponding point in the complex plane.
//
for (y = 0; y < image_data.height; y++)
{
for (x = 0; x < image_data.width; x++)
{
//
// This scales the <x, y> values into a smaller range of the
// complex plane. But it doesn't take into account the size of the
// canvas element. So if the canvas element changes size, this will
// need to change as well. This can be made automatic, but it would
// obcure the meaning for this example. It would be a good
// experiment to change these values and try and make the result
// general.
//
iterations = compute_escape_time((x  350.0) / 200.0,
(y  250.0) / 200.0,
100);
//
// This is a simple use of the iteration count. We are only looking
// at the bottom bit of the resulting escape time iterations. This
// results in the zebra striping look.
//
if (iterations & 1)
r = g = b = 255;
else
r = g = b = 0;
//
// Write the computed color value to the image_data at the current
// location.
//
set_pixel(image_data, x, y, r, g, b, 255);
}
}
// Finally, copy the resulting image to the canvas for display.
context.putImageData(image_data, 0, 0);
}
</code></pre>
<p>Syntax highlighted with <a href="http://prismjs.com">Prism</a>.</p>

Git Filter Branch
//socialhacker.com/posts/git_filter_branch/
Sun, 25 Mar 2012 03:14:00 0800
anton@socialhacker.com (Anton Staaf)
//socialhacker.com/posts/git_filter_branch/
<p>This HOWTO describes the steps required to extract a portion of a
large git repository into it's own separate repository.</p>
<p>I have found this useful numerous times because when I first started
to use git I created a single repository for all of my personal
projects. Since then I've come to appreciate having many smaller
repositories. So whenever I want to open up some new chunk of code
I use these steps to extract the history for just that chunk into a
new repository and then publish that.</p>
<h2 id="setup">Setup</h2>
<p>I always start by doing a fresh clone of the repository that I want
to extract from, so that I know I'm not messing with my primary
development environment. This has the added advantage that as long
as you don't clone with recursive, you won't have any submodules
checked out. If you have submodules then the filter branch can get
into trouble trouble.</p>
<pre><code class="languagebash">git clone git://source.socialhacker.com/... temp_clone
</code></pre>
<p>Then just to make sure I'm not going to do something stupid, I remove
the remote from the newly cloned repository.</p>
<pre><code class="languagebash">cd temp_clone
git remote rm origin
</code></pre>
<p>Now we're ready to run git filterbranch. In particular, I run the
subdirectory filter which replays all of your commits, only keeping
changes to a given subdirectory. You need to add the pruneempty
option to cause filterbranch to not include empty commits.</p>
<pre><code class="languagebash">git filterbranch \
pruneempty \
subdirectoryfilter &lt;directory&gt; \
 \
all
</code></pre>
<p>Now, at this point I like to fix up the history a little. In
particular I fix up the commit messages with the name and email
address I've decided on. For a while I hadn't set these correctly
and my early commits have something pretty useless. This will only
work if you're the only committer to your repository. If you have
multiple people committing, then this will wipe out their author names
and email addresses from their commits.</p>
<pre><code class="languagebash">git filterbranch \
f \
envfilter "export GIT_AUTHOR_NAME='Anton Staaf'; export GIT_AUTHOR_EMAIL='anton@socialhacker.com';" \
HEAD
git filterbranch \
f \
envfilter "export GIT_COMMITTER_NAME='Anton Staaf'; export GIT_COMMITTER_EMAIL='anton@socialhacker.com';" \
HEAD
</code></pre>
<p>The final step before you can push your new repository is to remove
all of the old information about the commits that you no longer want
to be visible. The first line below clears out the reflog, so that
it doesn't maintain references to the old state of the repository.
The second line does a garbage collection run on the repository. This
will remove any objects that are no longer referenced.</p>
<pre><code class="languagebash">git reflog expire expire=now all
git gc aggressive prune=now
</code></pre>
<p>At this point you can add a new remote and push your repository.</p>

Diet Planner
//socialhacker.com/posts/diet_planner/
Sat, 17 Mar 2012 00:00:00 +0000
anton@socialhacker.com (Anton Staaf)
//socialhacker.com/posts/diet_planner/
<p>The <a href="//socialhacker.com/applications/diet_planner/diet_planner.html">Diet Planner</a> is a simple
javascript application that can calculate grams of fat, protien, and
carbohydrates needed to gain or lose weight given various body metrics.</p>

Brute Force SSH Attack Protection
//socialhacker.com/posts/ssh_protection/
Tue, 12 Oct 2010 05:19:37 0800
anton@socialhacker.com (Anton Staaf)
//socialhacker.com/posts/ssh_protection/
<p>This HOWTO describes a couple things that you can do to secure your
SSH server on a Linux machine (Ubuntu, RedHat, Suse...).</p>
<p>This is useful because there are script kiddies all around trying to
break into computers. And I imagine that botnets writers will take
more interest in Linux as it's market share increases.</p>
<p>The pattern that I have seen is of many many requests from the same
IP address trying to guess users and passwords. Most of the requests
are trying to guess the root password.</p>
<p>There are a couple things we can do to slow these attackers. The
most obvious is to configure ssh to only allow logins from a couple
select users. And to disallow remote login by the root user. We can
also use IPTables to only allow a limited number of connections per
minute. And finaly, we can move the SSH server to a different port
on the machine. I don't know if this actually causes the attackers
any pause however. They may just be trying all of the open ports.</p>
<p>There are more complex solutions to the problem. Port knocking or
log parsing come to mind. But I've opted for the simplest solution
that doesn't impact usability in my case.</p>
<p>The use of IPTables to limit repeated connections is based on work
by Kevin van Zonneveld. You can see his approach on <a href="http://kevin.vanzonneveld.net/techblog/article/block_brute_force_attacks_with_iptables/">his blog</a></p>
<h2 id="whatisiptables">What is IPTables</h2>
<p>IPTables is part of the kernels network stack (I think). It is a
user configurable state machine that can be used to filter packets as
they are received, before they are forwarded or before they are
transmitted.</p>
<p>Our configuration will drop incoming packets that meet a specific set
of rules.</p>
<h2 id="sshdconfiguration">SSHD configuration</h2>
<p>The file /etc/ssh/sshd_config is used to configure the ssh server on
your linux machine. The changes I made to mine were to change "Port
22" to "Port xxxx" and to add "AllowUsers yyyy zzzz wwww" where xxxx
is the new port you want SSH to listen to. yyyy, zzzz and wwww are
the users that you want to have remove access. I also made sure
that the line "PermitRootLogin no" existed and was not commented
out.</p>
<h2 id="sshconfiguration">SSH configuration</h2>
<p>If you have changed the port that sshd listens to then you will
probably want to configure your ssh clients on any machine that you
would like to access your server from. In your home directory on
each of these machines you should find "~/.ssh/". In that directory
you can create a config file. It's just called config. Put the
following in that file. Again, xxxx is the new port that your ssh
server is listening to.</p>
<pre><code class="languagessh_config">Host your.server.name
Port xxxx
</code></pre>
<h2 id="networkscripts">Network scripts</h2>
<p>In Ubuntu there are directories that contain scripts to run when an
interface comes up or goes down. These are convenient places to put
the IPTables commands needed to drop attackers packets. The
directory for scripts to run when a network interface comes up is
/etc/network/ifup.d. And the directory for scripts to run when a
network interface goes down is /etc/network/ifdown.d. We will
create one file in the ifup.d directory and a symlink in the
ifdown.d directory. We do this to consolidate the logic in a single
location. We can use the MODE variable to determine if the interface
is coming up or going down.</p>
<p>In /etc/network/ifup.d/sshprotection put the following.</p>
<pre><code class="languagebash">#!/bin/bash
SSH_IFACE="eth1"
SSH_PORT=xxxx # This should be the port you've moved your ssh server to, or 22 if you haven't moved it.
SSH_PERIOD=60
SSH_COUNT=8
#
# Only add the rules to the interface that SSH is actually listening on.
#
if [ "$IFACE" != "$SSH_IFACE" ]; then
exit 0
fi
case "$MODE" in
start)
IPTABLES_ACTION="A"
;;
stop)
IPTABLES_ACTION="D"
;;
esac
/sbin/iptables $IPTABLES_ACTION INPUT \
i $IFACE \
p tcp \
dport $SSH_PORT \
m state \
state NEW \
m recent \
set \
name SSH
/sbin/iptables $IPTABLES_ACTION INPUT \
i $IFACE \
p tcp \
dport $SSH_PORT \
m state \
state NEW \
m recent \
update \
seconds $SSH_PERIOD \
hitcount $SSH_COUNT \
rttl \
name SSH \
j DROP
</code></pre>
<p>This file needs to be executable by root. You can use the following
command line to make it so.</p>
<pre><code class="languagebash">chmod u+x /etc/network/ifup.d/sshprotection
</code></pre>
<p>And in /etc/network/ifdown.d create a symlink to the sshprotection
file in ifup.d using the following command line. This command line
assumes you're in the ifdown.d directory.</p>
<pre><code class="languagebash">ln s ../ifup.d/sshprotection
</code></pre>

Port Forwarding
//socialhacker.com/posts/port_forwarding/
Wed, 20 May 2009 23:10:10 0800
anton@socialhacker.com (Anton Staaf)
//socialhacker.com/posts/port_forwarding/
<p>This HOWTO describes the steps required to setup your RedHat (well any Linux
distro) firewall to forward the port used by gtkgnutella to a machine on your
internal network. This is useful because it allows your gtkgnutella client
to behave in a non firewalled mode and thus more of the gnutella network is
available to you. In particular, other machines that are behind firewalls that
can handle push requests will become available to you.</p>
<h2 id="whatisportforwarding">What is Port Forwarding?</h2>
<p>Port forwarding is a feature of the IPTables system. It allows one
computer to forward connections made to it so that another computer
can actually process the request. If you want a very simple metaphor
you can think of it as mail forwarding. Each computer has a number
of addresses called ports, and IPTables allows (among other things)
connections to these ports to be sent to another computer. The most
common use of port forwarding that I am aware of is allowing servers
to run on machines that would normally be hidden behind a firewall.</p>
<h2 id="firewallscript">Firewall script</h2>
<p>I am going to assume that you are using the default firewall script
that comes with RedHat or whatever distribution you are running. My
system is currently running RedHat 8.0 (heh, not anymore). And I am
using a firewall script called rc.firewall2.4. You should be able to
find it in your /etc/rc.d directory. If you don't find it it may be
that I had to install it and just don't remember. :) You can search
for rc.firewall2.4 on Google and find many copies.</p>
<h2 id="setup">Setup</h2>
<p>My goal was to make gtkgnutella work in a nonfirewalled mode from
within my firewalled LAN. To do this people suggested a line of the
form:</p>
<pre><code class="languagebash">$IPTABLES t nat I PREROUTING p tcp i $EXTIF dport 6346 j DNAT to 192.168.0.2:6346
</code></pre>
<p>Where $IPTABLES is the iptables executable, $EXTIF is the external
ethernet interface (I use two ethernet cards in my firewall), port
6346 is the gtkgnutella port and 192.168.0.2 is the machine on my
internal network on which I wished to run gtkgnutella.</p>
<p>With the rc.firewall2.4 script this doesn't quite work. The reason
is that by default any connection that would open a new session from
the outside world is dropped. This is done with the line:</p>
<pre><code class="languagebash">$IPTABLES P FORWARD DROP
</code></pre>
<p>The solution is to add a rule into the FORWARD chain that causes
connections from the outside world to port 6346 to not be dropped,
but instead to be accepted. Then the PREROUTING rule above will be
encountered and the connection will be forwarded to the internal
machine as desired. The line to accomplish this is:</p>
<pre><code class="languagebash">$IPTABLES A FORWARD i $EXTIF o $INTIF p tcp dport 6346 j ACCEPT
</code></pre>
<p>I placed this right before the line:</p>
<pre><code class="languagebash">$IPTABLES A FORWARD j LOG
</code></pre>
<p>I did this because this line will will add a rule that causes all
rules added after it to not be checked.</p>

Virtual Hosting and SSL
//socialhacker.com/posts/socialhacker/virtual_hosting_and_ssl/
Tue, 05 May 2009 00:28:33 0800
anton@socialhacker.com (Anton Staaf)
//socialhacker.com/posts/socialhacker/virtual_hosting_and_ssl/
<p>All right, now that we have some blogs up. We will want to enable
SSL/TLS security, also known as https. The reason you want this may be
obvious to some. But to spell it out for you, if you don’t use https
to connect to your administrative pages in Movable Type while you’re
sipping on your latte, then everyone else that’s on that wireless
network can see you type your password in, plain as day. And by “can”,
I mean there is nothing preventing them from watching your traffic.
Most likely, no one is, but you never know.</p>
<p>There are a couple of complications that we will need to work through
though. Firstly, SSL and name based virtual hosting are mostly
incompatible. And secondly, unless you get a Certificate Authority,
such as Verisign, to sign your SSL key you and your security conscious
visitors will be presented with an ugly message from the browser
saying that your site is trying to identify itself with an invalid
security certificate.</p>
<p>So, why are SSL and name based virtual hosting mostly incompatible?
Well, it turns out that the way name based virtual hosting works is
for the browser to send to your web server the name of the server it’s
trying to connect to. And then your web server uses that information
to look through the list of virtually hosted domains until it finds a
match. Then the page the browser wants is sent from the server to the
browser. But if you have connected to the web server using an https
connection then the communication channel needs to be encrypted. So
the server needs to send the browser the public key of the domain the
browser is trying to connect to. But the server doesn’t yet know what
domain the browser is trying to connect to, because that information
is part of what will eventually be encrypted and sent by the browser.
Apache will just serve the first certificate it finds in this case.
So all but the first domain in your list of virtually hosted domains
will cause the browser to issue an additional warning, that the
certificate is for the wrong domain. This isn’t a big problem for
large hosting companies or business, they can just assign a separate
IP address to each domain. And then use that extra information to
configure the web server, allowing it to pass the correct domain
specific key back to the browser. For us little guys, that’s not
really a suitable approach. You can do something similar by having
your web server listen on a bunch of different ports, one for each
domains SSL connection. But then your URLs will have to have the port
number in them as well. Not a really classy solution. There is a
solution to this problem in the works. It’s called “Server Name
Indication” or SNI, and it’s part of the TLS protocol. Unfortunately
it’s still not readily available (see
<a href="http://www.alexanderkiel.net/2008/04/22/statusoftlssni/">this</a> page).
So, what’s the solution? It’s pretty simple actually, just use
one certificate for all of your domains. There is an extension that
allows for multiple domain names to be associated with a single
certificate. When a browser receives such a certificate, it looks at
all of the domain names and if any of them match it is satisfied.
There seem to be some security issues with this feature (see
<a href="http://nils.toedtmann.net/pub/subjectAltName.txt">this</a>
page). But since we are mainly interested in using it to authenticate
ourselves with our own server, it’s not a big deal, I think. And that
brings us to our second issue. We can pay Verisign to generate a
certificate for us, or we can sign it ourself. If you pay Verisign (or
other Certificate Authority) then anyone that browses your web site
with a secure https connection will feel right at home, secure even.
If you sign the certificate yourself, then viewers will be presented
with a nastygram from their browser. Since I am mainly interested in
being able to securely access my servers from insecure networks, I’m
happy to sign the certificates myself.</p>
<p>First you need to enable SSL in your Apache configuration. In the
Apache2 configuration for Ubuntu these files are located in
/etc/apache2. You’ll need to make sure that your ports.conf file
contains something like the following:</p>
<pre><code class="languageapache_config">Listen 80
<IfModule mod_ssl.c>
Listen 443
</IfModule>
</code></pre>
<p>This causes Apache to listen on port 443 for connections as well as
port 80. Port 443 is the https port. And your conf.d/namevirtualhosts
file should look something like:</p>
<pre><code class="languageapache_config">NameVirtualHost *:80
NameVirtualHost *:443
</code></pre>
<p>This tells Apache to look up virtual hosts by name for traffic coming
in on either port. Next you need to make sure that your
conf.d/ssl_certificate file looks something like:</p>
<pre><code class="languageapache_config">SSLCertificateFile /etc/apache2/ssl/serverwide.crt
SSLCertificateKeyFile /etc/apache2/ssl/serverwide.key
</code></pre>
<p>You can see that I’ve called my certificate and key files serverwide
to make it obvious that they are used by all domains served by this
server. It is very important that these files have their permissions
set so that only root can read them. You’ll also need to make symlinks
from the ssl.conf and ssl.load files in your modsavailable directory
to your modsenabled directory.</p>
<p>Now we’re ready to generate and sign our key and certificate. Once you
have generated the certificate you can inspect it’s contents with this
command.</p>
<pre><code class="languagebash">openssl x509 in serverwide.crt noout text
</code></pre>
<p>To generate a key use the following command. You will be asked for a
pass phrase. It is important that you remember this pass phrase or
your key will be lost to you forever. Or at least until computers are
powerful enough to brute force crack your key.</p>
<pre><code class="languagebash">openssl genrsa des3 rand /dev/urandom out serverwide.key 1024
</code></pre>
<p>Once you have a key you can create and sign a certificate with the
following command. You will be asked for the pass phrase you entered
above. This is because the key is protected by that pass phrase and
can’t be used without it. This certificate will be valid for one year.</p>
<pre><code class="languagebash">openssl req config server.config new key serverwide.key out serverwide.crt x509 days 365
</code></pre>
<p>Most of the options we need to pass to OpenSSL to create and sign the
certificate can be passed in a configuration file. The command line
above assumes the configuration file is called server.config. Below
is an example server.config file, the main lines of interest are in
the alt_names section. The alt_names section is where you can put all
of the virtually hosted domains on your server. The browser will look
for a match with any of those domains when the server passes it the
certificate we have just generated. I also found that subjectAltName
had to be in both the v3_req and v3_ca sections.</p>
<pre><code class="languageopenssl_config">[ req ]
default_bits = 1024
default_md = sha1
distinguished_name = req_distinguished_name
prompt = no
string_mask = nombstr
req_extensions = v3_req
x509_extensions = v3_ca
[ req_distinguished_name ]
countryName = &lt;country code&gt;
stateOrProvinceName = &lt;state&gt;
localityName = &lt;city&gt;
organizationName = &lt;whatever, could be your name&gt;
organizationalUnitName = &lt;again, whatever&gt;
commonName = www.domain1.com
emailAddress = webmaster@domain1.com
[ v3_req ]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
subjectAltName = @alt_names
[ v3_ca ]
subjectAltName = @alt_names
[ alt_names ]
DNS.1 = www.domain1.com
DNS.2 = www.domain2.com
DNS.3 = www.domain3.com
</code></pre>
<p>The key that we have generated will have a pass phrase associated
with it (the one you entered when you generated the key). This pass
phrase will need to be entered every time you restart your apache
server. There are ways of removing this extra security, but if you
want to do that I’ll let you look that one up elsewhere. For me with
a server running on a UPS, I reboot or restart apache a couple of
times a year at most. The added security is well woth it. If your
server get’s compromised, and it will eventually, then your security
key will be coppied. And that is as they say, a bad thing.</p>
<p>And finally, in your site configuration file, probably in
/etc/apache2/sitesavailable, you will need to add the following:</p>
<pre><code class="languageapache_config"><VirtualHost *:443>
ServerName www.domain1.com
ServerAlias domain1.com *.domain1.com
DocumentRoot /var/www/domain1
SSLEngine On
</VirtualHost>
</code></pre>
<p>This is the Virtual host configuration file for your secured site.
You’ll want to add any additional configurations to it from your
normal *:80 configuration section.</p>

Virtual Hosting and Movable Type
//socialhacker.com/posts/socialhacker/virtual_hosting_and_mt/
Sat, 02 May 2009 11:33:15 0800
anton@socialhacker.com (Anton Staaf)
//socialhacker.com/posts/socialhacker/virtual_hosting_and_mt/
<p>It was a lot harder than I anticipated to get Movable Type to run
from a single global install on all of my virtually hosted domains.
So in the spirit of sharing, here’s how I did it.</p>
<p>First, install movable type into a directory at the root of your web
servers directory structure. I put mine in /var/www/shared/. The
resulting directory structure contained:</p>
<dl>
<dt>/var/www/shared/cgibin/mt</dt>
<dd>This directory contains pretty much everything in the Movable Type
tarball.</dd>
<dt>/var/www/shared/mtstatic</dt>
<dd>This directory is the mtstatic directory from the Movable Type
tarball. I moved it out to the top level of the shared directory
because I have Apache configured to not serve documents from the
cgibin directory.</dd>
<dt>/var/www/shared/conf</dt>
<dd>This directory will contain the configuration files for all of the
sites you will be virtually hosting.</dd>
</dl>
<p>Next configure apache for each of your virtually hosted domains. I
assume you already have virtual hosting up and running. The
configuration file for socialhacker.com looks like this:</p>
<pre><code class="languageapache_config"><VirtualHost *:80>
ServerName www.socialhacker.com
ServerAlias socialhacker.com *.socialhacker.com
DocumentRoot /var/www/socialhacker
AddHandler cgiscript .cgi
SetEnv MT_HOME /var/www/shared/cgibin/mt
SetEnv MT_CONFIG /var/www/shared/conf/socialhacker.cgi
ScriptAlias /cgibin/ /var/www/shared/cgibin/
Alias /mtstatic/ /var/www/shared/mtstatic/
</VirtualHost>
</code></pre>
<p>The important bits here are how you set up the alias’ and the
environment variables. And all of this is covered in <a href="http://www.movabletype.org/documentation/enterprise/managingmultipleinstancesof.html">this article</a>.</p>
<p>Finally, you need to create a configuration file in the shared/conf
directry for your site. I did this by hand, which you’ll need to do as
well since Movable Type won’t set most of these options in the
configuration file it generates.</p>
<pre><code class="languagemovable_type_config">CGIPath /cgibin/mt/
StaticWebPath /mtstatic/
StaticFilePath /var/www/shared/mtstatic/
PluginPath /var/www/shared/cgibin/mt/plugins/
TemplatePath /var/www/shared/cgibin/mt/tmpl/
WeblogTemplatesPath /var/www/shared/cgibin/mt/default_templates/
ObjectDriver DBI::mysql
Database <your database name>
DBUser <your database user>
DBPassword <your database password>
DBHost localhost
MailTransfer smtp
SMTPServer smtp.<your provider>.com _(probably)_
</code></pre>
<p>And there’s the real magic. You have to specify paths to the Static
content as well as both Template directories, and the Plugin
directory. If you forget the first template directory you won’t get
very far as the administrative pages won’t load. But if you forget
the second template path you’ll get all the way to making a post and
find that all of the files in your blog directory are zero length. If
you forget the Plugin path you’ll be missing all of your plugins.</p>
<p>Hopefully you’ve found this useful in setting up your own Movable Type blogs.</p>