Single language for the entire project. We knew we wanted the user interface to be on the web, so that the user would not have to install any software and it could be used on any computer/tablet/smartphone. Modern user interfaces are always written in Javascript. Using Javascript on the robot allows us to use one language everywhere, so there is less context switch to deal with when moving between code for the interface and on the robot. This also allows us to easily share data structures between the user interface and the robot.

Event-driven. Node.js, the platform that runs our Javascript code on the robot, uses a non-blocking, event-driven model. Unlike languages like C where code runs sequentially, code in Node.js runs based on events. When an event fires, one or more functions are run to handle that event. Examples of events are timers to run code on a set interval, hardware interrupts, new data from a sensor such as our LIDAR, or more high-level things such as an updated calculation of our position. This allows us to organize our code into a set of small pieces that handle events and create new events, then we don’t have to worry about running code at the right time–it just happens. This type of organization is ideal for robotics applications.

Non-blocking. Since all code runs in response to an event, we never have to block, or wait for something to happen in our code. This is common in projects based on Arduino–it is common there to sleep for a short time while you wait for a task to finish. This is bad as nothing else can happen while this happens, thus “blocking”. In Node.js we just have an event fire when the task finishes, then something else can run while we’re waiting. This allows our code to get more done on a single thread.

Single-threaded. This can be a disadvantage as we can only do one thing at a time, however in our case we have a single-core processor and a non-blocking architecture, reducing the disadvantages of being single-threaded significantly. The advantage of this is that we don’t have to worry about coordinating data and tasks between threads, which can be quite difficult. Single-threaded code is much simpler and thus both easier to understand, faster to write, and less likely to have bugs. This does mean we must be careful not to spend a large amount of time handling a single event, as that would then block other events–this is easily solved by breaking that code into multiple event handlers and events, which has the side affect of being easier to understand.

NPM. The Node Package Manager is similar to the concept of Ruby Gems, 3rd party IP in VHDL, or DLL files in Windows. It is even better than those, however, as there is a huge number of high-quality libraries available for use, which can be installed with a single command and virtually never conflict with each other, even when different versions of the same library are used at the same time. Most of these libraries are open source and free to use in projects such as ours, most of them run in ARM just as well as on x86, and there are libraries written specifically to help interface with the hardware we use, such as the GPIOs on the BeagleBone Black. The existence of these easy-to-use libraries means we don’t have to spend time re-writing commonly-used code, we don’t have to spend a lot of time searching for and installing libraries, and we can focus on writing the code that is unique to our project.

Performance. Javascript has a reputation for being slow, but this is in fact no longer the case. It is interpreted on first run, and a just-in-time compiler is used to compile frequently run code to machine language. Javascript is usually about as performant as Java, more performant than interpreted languages such as PHP or Python, although obviously not as performant as native C applications. For our application, the performance of Javascript is more than enough, and the benefits over a lower-level language such as C are worth it. It being faster than Java is due in part to the event-based, non-blocking nature of Node.js, and partly because most math in Javascript is just faster than math in Java. The two areas where Javascript is not as good are bit operations, but we do very few of those, and long CPU-intensive calculations which block other events from being handled, and can be avoided by reducing the size of event handlers. The fact that Javascript is initially interpreted means startup time is very fast, allowing us to run new code quickly, which is also good. If we do need to do something very CPU-intensive such as image processing, it is very easy to delegate to code written in C/C++.

Cross-Platform. All the code we write will run on any ARM processor, and much of it will run on x86 as well. This means we can change our SoC fairly easily if desired, and we just have to change the pin mappings and device tree overlays. The actual code will not need changed, or even re-compiled. We can also run portions of the robot code within a browser for simulations.

Functional Programming. Although Javascript is an imperative language, it borrows heavily from declarative and functional languages, and makes it easy to write functional code. Javascript allows us to write small modules, objects, and/or functions imperatively, then combine them in a declarative manner. This makes the individual modules simple and easy to understand, and the relationships between them easy to follow. This is similar to standard object-oriented programming but with greater composability. In other words, these modules can depend on or contain any other modules, in any order.

Javascript vs Java. We am not fond of Java as it is a verbose language and requires the use of the JVM, which is a quite large thing to depend on, particulary on an ARM processor. We also think Javascript is a much more elegant language to use than Java. Those of us who have used it have also never had good luck with Java applications, they seem to never work properly and the language does not seem fun to work with.

This blog post summarizes why we dislike Java:

Whenever I write code in Java I feel like I’m filling out endless forms in triplicate.

“Ok, sir, I’ll just need your type signature here, here, and … here. Now will this be everything, or…”

‘Well, I might need to raise an exception.‘

The compiler purses its lips.“An exception? Hmmm… let’s see…. Yes, I think we can do that… I have the form over here… Yes, here it is. Now I need you to list all the exceptions you expect to raise here. Oh, wait, you have other classes? We’ll have to file an amendment to them. Just put the type signature here, here, … yes, copy that list of exceptions….

Javascript vs Python. Python has often been used for projects like this before. However, it is interpreted (actually converted to bytecode like PHP) which makes it slower, although not as slow as Ruby. Javascript is also better at event-driven things, although Python can do them as well. Python does not have as many libraries, although it does have a library for most tasks. Finally, the code style is very different from the code for the user interface and is unfamiliar to us.

Javascript vs C. C would definitely be faster, however it would require more code as it is a lower-level language. Like Python, C isn’t designed for event-driven things, although it can do them. A big disadvantage of C is that it must be compiled before you can run it, meaning you must wait a while between writing code and executing it. This makes it take longer to write any code. Also, if there is something that we must do quickly, we can write something in C that does just that one task, and connect it to the Javascript code easily. Many of the libraries we use already do this.

Javascript vs Assembly. Building a SLAM robot in pure Assembly would be an exercise in self-torture. However if there is something that we must do very quickly we can write Assembly code for it and connect it to the Javascript code, or we can run Assembly on one of the PLUs of the BeagleBone Black. This was done for the air quality sensor, for example.