Wednesday, April 18, 2012

Still Roving Mars

On my way into work the other day I ran into a colleague from my days working on the Mars Exploration Rovers (MER).  At the time I was working MER she was a rover driver - one of the robotics engineers with the coveted job of assembling commands to drive the rover and use the robotic arm.  Turns out she's still on MER and now wearing one of my previous hats on the mission planning team (MPT).  Due to the infectious nature of the project, the excellent team, and the rewarding work, moving around the project to work different roles is not uncommon.  I personally had 4 different roles during my ~four year tenure.

The MPT's primary purpose is to coordinate Ultra high frequency (UHF) communications with Mars-orbiting satellites (MRO, Odyssey, Mars Express) and X-band communications with Earth's Deep Space Network (DSN).  Around 2005 I wrote a series of software tools to automate the team's primary deliverable, the Rover's communications window table.  The code interprets the orbit data (time of overflight, RF predicts, data volume predicts, etc) and rover constraints (time of day, orientation, quantity of passes, data rates, ...) and outputs a table of communication windows to send to the rovers.  These windows used to uplnik the rover's daily set of commands and downlink science and engineering data.

Apparently, they're still using my software 7 years later!  Some intermittent contact with old teammates over the years indicate there have been no major changes to the code.  The significance of this began to sink in after we parted:
  • The software has produced well over 10,000 commands that the rovers have executed.
  • I built a process that has withstood the test of time and attrition.  I trained about 6 others (with built-in training features) before leaving the project and later they trained fresh meat.  The number of people trained and using the code at any given time between 2005 and 2012 is probably around 20.
I am very proud to have been a part of the MER team and extremely pleased to see that some of my work is still contributing to a successful mission.

Wednesday, March 14, 2012

How to make a Twilio Voice App Hosted by Heroku

Twilio is a relatively new cloud-based platform that allows one to create and scale voice, VoIP and SMS text messaging applications.  Here, we'll walk through building an app to allow a caller to check the high and low tide times in Santa Monica for the day of the call.  We'll use TwiML, Twilio's XML-like language for issuing HTTP GET and POST requests between your server and theirs. 

In order to run your app, you'll need to find a place to host your code.  For this example, I'll use a basic Heroku app.  First, we'll build the Heroku app using ruby and Sinatra, then we'll incorporate the TwiML and the Twilio Sandbox.

If you don't already have a github account and its version control system installed on your local machine, follow these directions.  If you don't already have a Heroku account or aren't setup to push code from your local machine, follow these instructions.  If you have no idea what I'm talking about, perhaps this panda can set you straight.

Rather than reinvent the wheel, we'll clone an existing github repository that has a basic skeleton for making one page static sites on Heroku.

# Make yourself a directory for the app
$ mkdir twilio_static

# Pull a clone of the skeleton app
$ git clone git://github.com/dpritchett/wwebsite.git twilio_static/
$ cd twilio_static/

The ./twilio_static/Gemfile looks like this
source 'http://rubygems.org'
gem 'sinatra'
gem 'heroku'

# For Twilio App
gem 'hpricot'
gem 'twilio-ruby'
gem 'builder'

Install the gems...
$ bundle install

Now we need to create a repository on github.

$ git init
$ git add .
$ git commit -m "initial commit"

Go to github and create new repository on github: https://github.com/<username>
Next, associate the local files with the new repository.

# Got an error because the local name of the remote repository already exists
$  git remote add origin git@github.com:jonesbb/twilio_static.git
fatal: remote origin already exists.

# Found a workaround on Stack Overflow and was able to continue

$  git remote rm origin
$  git remote add origin git@github.com:jonesbb/twilio_static.git
$  git push -u origin master

# now create heroku app

$ heroku create
$ git push heroku master

To get a preview of the basic app, you can run the server locally
$ ruby -rubygems app.rb

Point your browser here to see the app on your local server: http://localhost:4567/

*** You need to restart the app.rb file each time you change it! ***

Get a xml file of tide data from NOAA and place it in the /public folder of the app.  For extra credit you could have the app extract that data directly from the NOAA servers, but that's outside the scope of this demo.

Start a ruby script to parse through the tide data and output the high/low tides for the current day.

Here's what's in the initial version of my public/twilio_tides.rb
require 'rubygems'
require 'hpricot'
require 'builder'


# Get Today's Date in yyyy/mm/dd format
t=Time.now
cdate = t.strftime("%Y/%m/%d")


# Read in the tides xml file
xml = File.read('public/9410840_2012_tides.xml')


# Initiate the variable, prepending an intro.
@tide_today = ["Today's Tides are as follows:"]


# Find the tide info for today's date
# There's usually more than one hi/lo for a day, so push all into an array
doc = Hpricot::XML(xml)
(doc/:item).each do |dat|
    tide_date = (dat/'date').inner_html
    tide_time = (dat/'time').inner_html
    tide_size = (dat/'predictions_in_ft').inner_html
    tide_hilo = (dat/'highlow').inner_html
    if tide_date == cdate then
        if tide_hilo == "H" then
            tide_hilo = "high"
        elsif tide_hilo == "L" then
            tide_hilo = "low"
        end
      @tide_today << "#{tide_hilo} tide, #{tide_size}feet at #{tide_time}"
    end
end

# Join the array into one string and define instance variable to pass to app.rb
@@tide_today = @tide_today.map! { |p| "#{p}" }.join(", ")

Add to the app.rb to test out the new twilio_tides.rb script.
# Setup a test of the tides script
get '/hello' do
  puts "Hello, world!"
  load 'public/twilio_tides.rb'
  puts "Here's tide info: #{@@tide_today}"
end
Run the app locally as discussed above and navigate to:
http://localhost:4567/hello (which initiates the get request to run the code in /hello).
You should see the "Hello World" and "Here's the tide info:..." print with the tide data for today.

Now you're ready for the TwiML creation.  The additional code in app.rb below makes use of the TwiML verbs, <Say> and <Gather> to tell the caller what the tides are and then to gather the caller's feedback regarding the option of repeating the info or ending the call.

Here's the final app.rb file.
require 'sinatra'
require 'builder'

# Define the route for the index.html - static homepage for the app
get '/' do
      File.read(File.join('public', 'index.html'))
end

# Setup a test of the tides script
get '/hello' do
  puts "Hello, world!"
  load 'public/twilio_tides.rb'
  puts "Here's tide info: #{@@tide_today}"

end

# Define a method that accepts both post and get requests
# This is useful because of the /loop redirect to /tides
def get_or_post(path, opts={}, &block)
  get(path, opts, &block)
  post(path, opts, &block)
end


# Create the TwiML response to read out the tide data
get_or_post '/tides' do
  load 'public/twilio_tides.rb'
  builder do |xml|
    xml.instruct!
    xml.Response do
            xml.Say("Hi #{@@tide_today}")
            xml.Gather(:action=>"/loop", :numDigits => 1) do
                  xml.Say("Press one to repeat or two to end this call.")
            end
    end
  end
end

# Loop the caller's feedback
post '/loop' do
    if !params['Digits'] or params['Digits'] != '1'
        builder do |xml|
              xml.instruct!
              xml.Response do
                xml.Say("Adios.")
              end
        end
    else
      redirect '/tides'
    end
end

Now let's push all the code to Heroku so we can access it from Twilio.

$ git add .
$ git commit -m "added TwiML to app"
$ git push
$ git push heroku

Take note of the Heroku
http://sharp-stream-4312.heroku.com

Go to Twilio and create an account (if you haven't got one already).  On your account's Dashboard, you'll see the "Sandbox."  Put the new Heroku URL, directing to the get_or_post method's /tides, in the Sandbox's Voice URL.

http://sharp-stream-4312.heroku.com/tides

Click SAVE and then try calling.  For more information, Twilio's website has many more examples of how to interface with their servers using either their REST API or TwiML.

Tuesday, February 28, 2012

Custom Domain Names on Heroku

Adding a custom domain name from namecheap to your Heroku app is straight forward.

  1. Do the first few steps of Heroku Setup to add the custom_domain add-on and inform Heroku of the domain(s) you are using.
  2. Go to Namecheap, login to your account and find the domain you want to use.
  3. Click on the URL Forwarding link to modify that domain's URL forwarding and...
    • update the IP ADDRESS/URL for both the "@" and "www" host names to be "proxy.heroku.com." without the quotes, but be sure to include the final period
    • update the RECORD TYPE to "CNAME (Alias)" for both
  4. You're good to go.  See an additional example and screen shots at this other post.

Friday, February 24, 2012

Random Unix Cmd For Listing Files

 A random tip on searching directories on unix...

I'm looking to create a single-column list of file names inside a directory.

I don't want any of the meta-data (eg. modification time, permissions...)

$ ls -C1
 file1.txt
 file2.txt
 file3.txt

For more info:
$ man ls

Wednesday, February 15, 2012

First jQuery Rails App

Creating a new app to learn jQuery basics.  I'll create a basic app per my previous post, then attempt follow this guy Jon Raasch's simple jQuery slideshow 'tutorial.'

# First, check status on versions
$ rvm --default use ruby-1.9.2-p180
Using /Users/jonesbb/.rvm/gems/ruby-1.9.2-p180
$ ruby -v
ruby 1.9.2p180 (2011-02-18 revision 30909) [x86_64-darwin10.7.0]
$ rails -v
Rails 3.0.11

# Created new rails app
$ rails new simple_jquery_slideshow1

# added Heroku gem to Gemfile

Found this site for setting up the rails 3 environment for jQuery.  Follow steps on the site and make sure to update the jquery.js filename in your config file to match what you download from jquery later on in this post.

# Remove the default javascripts from the public/javascripts/ directory.
$ rm controls.js dragdrop.js effects.js prototype.js rails.js

# Setup github repository from project home directory, ./simple_jquery_slideshow1/
$ git init
$ git add .
$ git commit -m "initial commit"

# create new repository on github: https://github.com/jonesbb, name it simple_jquery_slideshow1
$ $ git remote add origin git@github.com:jonesbb/simple_jquery_slideshow1.git
$ git push origin master

# Add jquery to Gemfile with this line:
gem 'jquery-rails', '>= 1.0.12'

$ bundle install

# Using a submodule in git to add jQuery driver to public/javascripts/jquery-ujs/
$ git submodule add git://github.com/rails/jquery-ujs.git public/javascripts/jquery-ujs

# Do a submodule init, which results in the following:
$ git submodule init
Submodule 'public/javascripts/jquery-ujs' (git://github.com/rails/jquery-ujs.git) registered for path 'public/javascripts/jquery-ujs'

Next, I downloaded the minified version (1.7.0) of jquery from the jquery website.  Although 1.7.1 existed, I figured that the kinks were worked out of 1.7.0.  Maybe a bad assumption, but oh well.

Put the downloaded jquery.min.js file inj /public/javascripts/

# Updated github and created Heroku app
$ git add .
$ git commit -m "added jquery"
$ git push
$ heroku create
# created http://vivid-leaf-3508.heroku.com/
$ git push heroku master
# Checkout a new Git branch to start creating the app's pages
$ git checkout -b basic-pages

# Create the pages controller
$ rails generate controller Pages home about contact

Downloaded the basic slideshow materials from Jon's website.

Created a ./public/stylesheets/custom.css file and put Jon's CSS there.

#slideshow {
    position:relative;
    height:350px;
}

#slideshow IMG {
    position:absolute;
    top:0;
    left:0;
    z-index:8;
}

#slideshow IMG.active {
    z-index:10;
}

#slideshow IMG.last-active {
    z-index:9;
}



# added Jon's html code to the ./app/views/pages/home.html.erb file
Slideshow Image 1 Slideshow Image 2 Slideshow Image 3 Slideshow Image 4

At first, I got lots of errors trying to find the image files.  Turns out you need to specify the images using the erb syntax as shown here (defaults to images in the ./public/images/ directory).  More on routing here.

<%= image_tag "image1.jpg", :alt=>"Slideshow Image 1", :class=>"active" %> <%= image_tag "image3.jpg", :alt=>"Slideshow Image 3" %> <%= image_tag "image4.jpg", :alt=>"Slideshow Image 4" %>

Put Jon's images (because I'm lazy for this demo) in the ./public/images/ folder.  They're all the same size, so don't have to deal with possible issues there.

Added the following js code to ./public/application.js file.

function slideSwitch() {
    var $active = $('#slideshow IMG.active');

    if ( $active.length == 0 ) $active = $('#slideshow IMG:last');

    var $next =  $active.next().length ? $active.next()
        : $('#slideshow IMG:first');

    $active.addClass('last-active');

    $next.css({opacity: 0.0})
        .addClass('active')
        .animate({opacity: 1.0}, 1000, function() {
            $active.removeClass('active last-active');
        });
}

$(function() {
    setInterval( "slideSwitch()", 5000 );
});

# Update the config/routes.rb file to map and name the routes:
# Replace the get statements in the routes file with these match commands...
  match '/contact', :to => 'pages#contact'
  match '/about',   :to => 'pages#about'
  root :to => 'pages#home'

# update the repository to remove the default index.
$ git rm public/index.html
$ git commit -am "Removed default Rails page"

Do a set of commits and merge the basic-pages branch back to master git branch. 
Success!

Tuesday, February 14, 2012

Syntax Highlighting in Blogs

Found a good tool to do syntax highlighting in blogs, so code snips should be more legible.  Will see about working that into the flow.  No promises I'll use it all the time.

HEROKU STACKS 101

When creating a new heroku app, Heroku defaults to one stack.  You can also specify which stack to use based on which version of Ruby you're using.  See the Heroku dev article on stacks.


# determine which one am currently using:
$ heroku stack
  aspen-mri-1.8.6
* bamboo-mri-1.9.2
  bamboo-ree-1.8.7
  cedar (beta)

The bamboo-mri is the default as of writing this.
Since I'm running this app on ruby 1.8.7 (damn Johnson gem), I need to migrate to the bamboo-ree-1.8.7 stack.  See Heroku's instructions on migrating stacks here.


# Test the migration to bamboo in a temp app:
$ heroku create --stack bamboo-ree-1.8.7 --remote trybamboo
Creating pure-water-6467... done, stack is bamboo-ree-1.8.7
http://pure-water-6467.heroku.com/ | git@heroku.com:pure-water-6467.git
Git remote trybamboo added


$ git push trybamboo master

Ok, slug compiled and deployment successful.  Looking at the site, it appears to be working (in the same no-java form as on the local machine).  Except, the h5 titles "Work" went back to white text and are no longer visible.  Thought I fixed that earlier.  Not going to fret about that right now, bigger fish to fry.

$ heroku stack:migrate bamboo-ree-1.8.7 --app radiant-river-4002
-----&gt; Preparing to migrate radiant-river-4002
       bamboo-mri-1.9.2 -&gt; bamboo-ree-1.8.7

       NOTE: You must specify ALL gems (including Rails) in manifest

       Please read the migration guide:
       http://devcenter.heroku.com/articles/bamboo

-----&gt; Migration prepared.
       Run 'git push heroku master' to execute migration.