Wishful Coding

Didn't you ever wish your
computer understood you?

Generic programming tutorial

I have wanted to teach you some programming since I started this blog, but I refrained from doing so, because there are so many ways to program, and I want to use them all.

What I’m going to attempt, is not to teach you a programming language, but teach about programming itself. This may seem useless to you, but my experience is that when you understand programming, the language does not really mater, and you can program in anything that is not excessively weird.

For practical reasons, any code examples will be written in NBC, Python, NXT-G and Clojure.

A computer

To understand programming, you first need to understand what a computer is. For our purpose, it suffices to think of a computer as a processor, a block of storage, and a block of memory.

This is true for desktops, smartphones, the NXT, and anything else with these components. Of course there are some other components involved, which can be divided in inputs(keyboard, sensor) and outputs(screen, motor).

What a computer does, is read instructions from the storage, execute them on the processor, which modifies the memory and reads/writes to the in- and outputs.

To give you an idea, you could put instructions in the storage that tell the computer to store the number 2 in memory, copy it, and multiply the two numbers, saving the result in memory.

A more useful set of instructions could put the input from the keyboard to the screen, or read a sensor, do some math and control the motor.

A compiler

When I said instructions, I did not mean instructions in plain English. Processor instructions are not easy to read and write for humans, that is why we let computers translate them for us.

In its most basic form, a compiler is a set of instructions which converts words like “add” and “read” to stuff that a computer understands.

More advanced compilers also allow you to define new words, such as “turn left”, in terms of other words, such as “motor on” and “motor off”.

A language

A language is a set of instructions, as understood by a specific compiler. A language consists of a few things.

A syntax

This is like grammar for compilers. A few examples of adding a number:

  • Python: 1 + 1
  • Clojure: (+ 1 1)
  • NBC: add 1 1 result
Which are all the same thing, except that NBC is a statement instead of an expression, more about that later.

An API

This is the hardest part of programming. But let me tell you, even good programmers don’t remember all APIs, you simply google them.

An API is the set of words at your disposal to express your problem. This API is different for every language.

In NBC there is a word called “OnFwd” which can be used with an output, like “OnFwd(OUT_A)”, but in Python, there is no such thing. Python doesn’t even know what a motor is, or what forward means.

However, people have already defined words to talk about the NXT in Python. To use words already defined elsewhere, we can say “from nxt.motor import Motor, PORT_A” in Python. Now we can say “Motor(my_nxt, PORT_A).run()”

Expressions

Expression have a value. The value of (+ 1 1) is 2, so we can also say (* 2 (+ 1 1)), which has the value 4.

People commonly say expressions ‘return’ a value, which is what you do when you define an expression in Python:

def expressions():
    return 2

Statements

Unlike expressions, statements do not have a value. What would be the value of “while True:”(the start of a loop in Python)?

Note that not all languages have expressions and statements.

NBC has only statements, which is why you write “add 1 1 result”, so that the result of the addition gets saved in memory.

Clojure has only expressions. if something has no useful value, it returns nil.

Python is a mixed bag.

References

So far I have talked about that block of memory as an abstract thing where you save and retrieve values. In reality, it is very useful to label the box you put it in.

For example, in Python you can say

x = 1
y = x + 1

These are statements that store the value of the expression. ‘x’ now references the value of 1, which is 1. ‘y’ is now a reference to the value of adding the value of x(1) to the value of 1(1).

Collections

So far we used numbers as values, but what if you want to talk about a collection of things?

languages usually provide means of defining a collection of things, and for doing things to the elements or the whole collection, like sorting it, or getting/setting elements.

An array of 5 integers in NBC:

dseg segment
  int reference[5]
dseg ends

Functions

We talked earlier about the words that make up an API. In most cases, words are also just references to values.

These values are usually called functions, and consist of a collection of other functions.

Not all languages have functions as values. In NBC, functions are statements, which don’t have a value. Clojure, however…

(def x 2)
(def square (fn [n] (* n n)))
(square x)

Here, I defined ‘x’ a reference to the value 2, and ‘square’ a reference to a function that multiplies a number by itself. The, I called the value of ‘square’ with the value of ‘x’, resulting in the value 4.

Learning a programming language

I hope to have given you a good understanding of how a programming language works. To actually start using a language like NBC, you need to find out a few things:

  • How do I use words/call functions?
  • How do I define references to values in memory?
  • How do I define new words?
  • What existing words do I have at my disposal?

A good starting place is usually a beginners tutorial. Google for “<language> tutorial” and click the first result.

After a section or two, they usually start to talk about how to do things. You might continue, or stop here, and get your hands dirty. If you run into trouble, simply google for “<language> how to <problem>” or find the function reference by searching for “<language> function reference>”.

If you are really in deep trouble, Stack Overflow is a great website for asking questions.

I hope this is enough preparation for you to start learning, and for me to focus on explaining how to do things in any language needed, like plotting a picture with the NXT ;-)

Fast PyCAM on Mac using Homebrew

Ever since I started working on my CNC mill, I have been looking for decent software to generate G-code for it.

I wrote a G-code interpreter for my machine, after I found out LinuxCNC doesn’t support my type of LPT stepper driver, but finding good software to turn a 3D model into G-code turned out to be hard.

I went down this list, but most of them where hard to install or impossible to configure. In 2D I had some luck with the Inkscape plugin, but I was lost for 3D.

With the mill in a working state, and nothing to mill, I decided to push forward with PyCAM. I skipped PyCAM previously, because of its dependencies, which weren’t all available in Homebrew.

Some experimentation revealed a few important things:

  • It runs okay on my Ubuntu netbook.
  • Toolpath calculations take a looong time.
  • Its CLI runs without OpenGL and GTK+
  • It supports multiple and distributed processors.

After I cancelled the Ubuntu calculations, I ran it headless on my Mac. While somewhat faster, it still took a long time to generate G-code.

The real speedup came later, when I found PyCAM supports Psyco. But rather than messing with Psyco, I followed the advice on the Psyco homepage, and found the headless PyCAM runs great, and very fast, on PyPy.

Psyco is unmaintained and dead. Please look at PyPy for the state-of-the-art in JIT compilers for Python.

After successfully running PyCAM headless, I finally put my teeth in the dependencies. Installation steps using Homebrew follow:

  1. Download PyCAM.
  2. Apply my patch to make sure it finds pygtk.
  3. brew install pygtk
  4. sudo easy_install PyOpenGL
  5. Wait for my pygtkglext Formula to be merged, or get it from my branch.
  6. brew install pygtkglext or brew install https://raw.github.com/pepijndevos/homebrew/master/Library/Formula/pygtkglext.rb

Now you should be able to just run ./pycam to see the GUI pop up. However, I use the following 2 commands to run a server on PyPy, for extra speed.

pypy pycam --start-server-only --server-auth-key=fietspomp --number-of-processes=4

python pycam --enable-server --remote-server=localhost --server-auth-key=fietspomp --number-of-processes=0

I’ll blog about the mill itself later. This morning I tried to mill a small sample project, but the mill is very inaccurate and jammed after a few layers.

Crazy Seq

crazy-seq, the solution to all your head-holding induced memory problems.

(defn crazy-seq [head f]
  (reify
    clojure.lang.ISeq
    (first [_] head)
    (more [_] (crazy-seq (f head) f))
    (next [this] (rest this))
    (seq [this] this)
    (equiv [_ _] false)))

(def s (crazy-seq 0 inc)) ; hold head
(dorun (take 100000000 s)) ; low fat
(nth s 10) ; recomputes
;=> 10

A normal lazy seq is made up of a car and a function that returns the cdr, which is then cached.

This means that if you store the first item and walk to the millionth, it will keep all these million items in memory.

What crazy-seq does, is that it simply does not cache the value. So you can walk to the millionth item, and it will only store the first and the current, the others are GC’d.

This means that walking twice will cost more CPU cycles, and it means that you get in trouble if the fn is not side-effect free.

Have fun.

Published on