Table of Contents
Setup and IDE
This page describes the main software components of the development environment, how they are set up and how to use them.
Component Overview
The following figure illustrates the main software components involved in the CRAM development process from the programming languages point of view. The figure has many inaccuracies (e.g. CRAM is not entirely written in Common Lisp, or ASDF is not actually a component of SBCL, it is, in fact, developed independently from SBCL but is automatically included when installing the latter, etc). On the other hand, it tries to keep things simple.
Compiler: SBCL
There exist many dialects of Lisp in the world: Clojure, Scheme, Racket, Emacs Lisp etc. CRAM is mostly written in Common Lisp. There are multiple compilers for Common Lisp (CL): SBCL, CMUCL, CLISP, ABCL, etc. (See CL Implementations). The ROS Common Lisp API and CRAM are developed with SBCL (Steel Bank Common Lisp) which implements the ANSI standard CL plus a number of useful libraries and more. As a standalone application callable from a Linux terminal, SBCL provides an interactive CL shell, somewhat similar to Python, although, in contrast to the latter, all code in SBCL is always compiled (as opposed to being interpreted), even the things coming through the interactive shell.
Buildsystem: ASDF
One thing is to compile a specific source file into machine code, and another thing is to combine the different building blocks, together with external libraries, into a coherent piece of software. For C++ the usual way to build the software is using the make
scripts and the utilities based on the latter, as, e.g. CMake. In the CL world the accepted build system is ASDF (Another System Definition Facility). ASDF supports all the modern CL implementations, including SBCL.
Middleware: ROS
All the software packages of CRAM on the highest level are ROS (Robot Operating System) packages. However, note that the Lisp code contained in the ROS packages is not compiled by the ROS build facility catkin. Also note that CRAM is not 100% Common Lisp, it has code written in other languages as well, so catkin is in fact used for the other languages (namely C++).
In addition to using ROS as a packaging / release system, CRAM also uses ROS as a communication layer between the different software components of a Robotics system. The implementation of the ROS communication API in Common Lisp is called Roslisp. As the ROS APIs in other languages, it uses XML-RPC (i.e., practically speaking, HTML) as a low-level communication protocol (e.g. for talking to the ROS master).
IDE: Emacs
SBCL + ASDF are already enough for developing and building CL software. But a more human-friendly development environment than the basic SBCL read-eval-print-loop would, of course, be more comfortable.
Emacs is the main IDE the CRAM development team is using. Although it is not graphical, when combined with extensions for the corresponding programming languages it has all the most important features one needs in an IDE: code autocompletion, jumping to function definitions, integration with version control software, automatized code compilation on package, file, single function level, support of an interactive environment where one can try out the newly written function immediately in the Lisp console, displaying documentation of symbols/functions inside the Emacs and looking up documentation in the Hyperspec using your favorite browser etc. In addition, for advanced users it has many possibilities for customization and development of custom features. Moreover, due to Emacs not having a GUI, one can connect to the running Emacs through SSH and run / develop the Lisp code from a remote machine that has an SSH-capable terminal.
On the other hand, the disadvantage of not having a GUI is that the whole functionality is invoked through hotkeys, so one needs to learn a lot of different key combinations, which takes time at the beginning but increases the speed of development once the hotkeys are inside one's fingers on the level of instincts.
As an interesting fact, many of Emacs's key combinations are the same also in most Linux shells, as, e.g., Ctrl-K
for killing the current line and Ctrl-Y
for pasting (yanking) it back into the shell.
Emacs is used by many people around the world, mostly as a text editor, it is also popular for Tex/Latex development, some people use it even for C++ and Python, and the CRAM team uses it for Common Lisp, obviously.
Please note that, as most other IDEs, Emacs requires an external compiler and build system (linker) to program with the user's language of choice (except, of course, Emacs Lisp, an implementation of which is included in Emacs because without it it wouldn't be able to run itself). An exception from this “rule” would be Visual Studio which per default includes a C++ compiler from Microsoft. Otherwise one always needs extra GCC, JDK, Python, Common Lisp implementations installed on the Operating System to go with the IDE.
Summary
CRAM is written in Common Lisp (CL). There are many different implementations (i.e. compilers) for CL. The compiler used in CRAM and Roslisp is SBCL. The build system that compiles different components (the CL files / packages / systems) located in different places in the file system, into one piece of software, is ASDF. It defines in which order the different components are to be compiled, where to find them, and is responsible for incremental code compilation.
The IDE used for CL programming in the CRAM community is Emacs. To connect the Emacs Lisp of Emacs (which is a different Lisp dialect) to the Common Lisp there is an Emacs extension called Slime. It's half written in Emacs Lisp, and half is in Common Lisp, the two halves talk to each other through TCP.
Emacs has a convenience extension for working with ROS called rosemacs. It can be used, e.g. for finding the source of a ROS package without knowing it's actual path but using the rospack find
utility.
To utilize the features of rosemacs when programming and building Common Lisp software there is also a slime-ros extension for Emacs which tells the CL build system where to find Lisp code of ROS packages.
For more info on how the different components are connected together check out the Connecting Things Together doc.
Setup
To setup the development environment one needs to (1) install the necessary components and (2) configure them.
If you followed the Installation instructions successfully (basic section is already enough) you should already have all the IDE components automatically installed. The default configuration is also already set up for you, so running roslisp_repl
in the shell will bring up a working IDE and you can start programming.
If you are interested to know what the default configuration does and what happens under the hood, check out the Emacs Configuration doc.
Useful Tips
Definitions
An Emacs buffer is the equivalent of window / tab in other editors. It can have a file associated with it that you can (or cannot depending on the privileges) edit, or it can be running a process (e.g. when you open the shell: M-x shell
). The minibuffer is usually a one-line part of the screen at the bottom of the Emacs window. The cursor in Emacs is called the point. Dired is the directory explorer mode of Emacs.
Textual representation of Emacs key bindings has a number of conventions:
- Short way of writing
Ctrl
,Alt
andShift
is:C
,M
andS
respectively. - RET stands for the
Enter
orReturn
key - if a key is supposed to be pressed together with another key, they're connected with a dash, e.g.
C-h
C-h b
means first pressCtrl
andh
together and thenb
separately (in contrast toC-h C-b
)- Commands like
M-x shell
mean: pressAlt
andx
together and then typeshell
into the minibuffer on the bottom of the screen.
Key bindings
Taken from the Slime manual:
“The Emacs online help facilities are your most immediate, up-to-date and complete resource for keybinding information. They are your friends:
- C-h k <key>: describe-key “What does this key do?”
- C-h b: describe-bindings “Exactly what bindings are available?”
- C-h m: describe-mode “Tell me all about this mode”
- C-h l: view-lossage “Woah, what key chord did I just do?””
You'd need to look things up yourself while you're working with Emacs. Whenever you think it would be nice to have a specific feature in Emacs it probably already exists, so Google it and write down the key combination. The cheat sheet for Emacs can be found in the Links section.
Below are listed some key combinations the author of this doc finds the most useful or most underrated.
General Emacs:
- C-M-Space: select expression (S-expression in Lisp)
- C-M-f (C-M-b): go forward (backward) one expression (in Lisp an S-expression)
- C-M-\: indent region
- M-; : comment out region (chooses correct commenting characters depending on the extension of the file you're editing)
- M-< (M- >): go to buffer beginning (or end)
- M-%: find-replace
- M-^: join line with previous (remove whitespace)
- M-\: remove whitespace around point
- M-x desktop-save (desktop-clear): save currently open files for the next session (don't lose them when exiting Emacs)
- C-x C-u (C-x C-l): upcase (downcase) region
Lisp (Slime) related (in a .lisp
file buffer):
- M-. (M-,): jump (jump out) to function definition
- C-c M-p: set package from the selected Lisp file as a package in REPL
- C-c C-c: compile the code block (usually function) where point is
- C-x C-e: evaluate expression
- C-c C-w c: who calls this function
- C-c C-m: macroexpand once
- C-c M-m: macroexpand recursively
- C-c C-z: switch to REPL
- C-c C-y: insert a call to the function defined around the point into the REPL
- C-c C-j: evaluate last expression in REPL
- C-c C-x t: list running threads (in case you're running roscore from Emacs or similar)
- M-x slime-browse-system: open the system directory in Dired
- C-c C-t: trace function at point
- C-M-<Backspace>: clear current input (in case you changed your mind on executing it), make sure you don't have system bindings for this key combination.
In REPL:
- C-j: go to new line and indent
- C-RET: close all unmatched parenthesis and evaluate
- C-c C-c: interrupt evaluation
- C-c M-o: clear the entire buffer except the prompt
- M-r (M-s): regexp search backwards (forward) through history
- All the shortcuts callable with
,
(coma) in the REPL (see,help
) - Right click on output to display the context menu (for inspecting elements, for example)
In Slime Inspector:
- RET: describe recursively
- l: go one recursive description up
- p: pretty print the object at point (most useful for strings and big arrays)
- .: view object source
In Slime debugger:
e
on a backtrace frame to evaluate an expression in that framev
on a backtrace frame to show source code of the function call
General Slime:
- Temporary buffers can be dismissed by pressing
q
. This kills the buffer and restores the window configuration as it was before the buffer was displayed. - Pressing
RET
is supposed to “do the most obvious useful thing”.
Check out more Slime features here.
Also, check out the very cool video demonstrating the awesome capabilities of Slime and Emacs. It's quite old and long but is worth it.
Useful extension packages
Except the standard features of Emacs you can turn on some extra capabilities by setting up your Emacs initialization file properly. There are also some external packages not yet integrated into Emacs that you can download from the Internet and place into your Emacs extensions directory in your $HOME
.
Yasnippet
With this Emacs package you can define templates (snippets) to put into your files by just pressing a simple key combination. E.g. for C++ you can set up an empty class definition as a snippet and then by typing class
and pressing TAB
in your .cpp
file the snippet will appear in the buffer. Or, you can define a snippet with the license you use (if it is opensource you should put a license header in every single file) and bring it into a file automatically using snippets with a simple key combination instead of actually copy-pasting things around.
Yasnippet is not included in Emacs per default, so you need to download it.
Whitespace
Using this package you can highlight lines that are longer than 80 characters, which is a bad coding style. You can also highlight empty whitespace in the end of a line etc. It is a standard package, you only need to turn it on and set it up.
Ido
Ido is an extremely useful package for showing you suggestions in the minibuffer when, e.g., opening a file. Just try it out. It's a standard package.
Winner mode
Have you ever spent loads of time trying to set up your Emacs windows nicely in a big screen with REPL in one specific window etc. and then suddenly pressed C-1
and lost your whole window configuration? The winner mode is for undoing and redoing the window configuration of your Emacs. It's a standard package, to turn it on you just need to add (winner-mode)
into your Emacs init file. The hotkeys are then C-c left
for undo and C-c right
for redo.
Links
SBCL manual: http://www.sbcl.org/manual/index.html
ASDF manual: http://common-lisp.net/project/asdf/asdf/
Slime tutorial video: http://common-lisp.net/project/movies/movies/slime.mov
Slime manual: http://common-lisp.net/project/slime/doc/html/
Common Lisp Hyperspec download: ftp://ftp.lispworks.com/pub/software_tools/reference/
Common Lisp quick start and good reference manual book: http://www.gigamonkeys.com/book/
Common Lisp “getting the feel of the language” book: http://www.paulgraham.com/onlisp.html
Emacs cheat sheet: http://www.gnu.org/software/emacs/refcards/
Paredit cheat sheet: http://www.emacswiki.org/emacs/PareditCheatsheet
— For corrections / suggestions / complains please write an email to the person who last edited this doc (you can find the username in the webpage footer).