roslisp Documentation


Lisp client library for ROS, the Robot Operating System.


roslisp is a library for writing ROS nodes in ANSI Common Lisp. See the tutorial at for how to set up roslisp for standalone compilation of lisp source files and/or interactive use. This page lists the functions available in the client library and other miscellaneous information. Detailed documentation about the functions is available within the Lisp environment using the documentation feature.

Integration with build system

Roslisp is integrated with the asdf build system. When using roslisp nodes from within a lisp environment, add the following lines to your .sbclrc:

(push #P"/path/to/roslisp/asdf/" asdf:*central-registry*)
(asdf:operate 'asdf:load-op :ros-load-manifest)

This extends asdf to use two additional rospack-based search methods to finding .asd files.

  • Given a system name foo, if the variable ros-load:current-ros-package is a nonempty string, it will look for a system named foo defined in asdf/foo.asd of the package or one of its ros dependencies. The file asdf/foo.asd will usually be a symbolic link to a file in whatever directory the actual source files are in. To dynamically bind the variable ros-load:current-ros-package and perform the load operation, the function ros-load:load-system can be used. It takes the name of the ros package as first parameter and an optional second parameter for the name of the system to load, which defaults to the ros package name.
  • Given a system of the form foo-msg, if there's a ros package called foo, the messages from this package will be loaded, and likewise for foo-srv and services.

You can also build standalone nodes in the CMakeLists.txt file. For example, roslisp_examples/CMakeLists.txt contains

rospack_add_lisp_executable(bin/talker roslisp-examples roslisp-talker:main)

This produces the executable roslisp_examples/bin/talker when built. When run from the command line, the executable does not load your standard .sbclrc init file. Rather, it loads ~/.sbclrc-roslisp (if it exists). It then sets current-ros-package to roslisp_examples, and loads the asdf system roslisp-examples into memory (using rospack). Next, it loads the files bin/roslisp-init.lisp and bin/roslisp-talker:main.init.lisp (if they exist). These are the places where you can put global, package-specific, and node-specific runtime customizations (customizing debug levels, setting optimization flags, modifying constants) respectively. Finally, it calls the function roslisp-talker:main. Also, when running standalone, the keyword :roslisp-standalone-executable is pushed on to the features list, in case you want to make use of this information in some way. Finally, setting the ROSLISP_BACKTRACE_ON_ERRORS environment variable before running the node will print debugging info if it dies.

Integration into emacs

The current trunk version of the rosemacs package contains a slime contrib that adds a slime repl shortcut to load systems in ros packages. Please see the rosemacs documentation for more information.

Debugging output

Roslisp provides a hierarchical, customizable-at-runtime, logging scheme, similar to rosconsole for roscpp. Debug topics are lists, e.g. (roslisp top). For such a topic, the debug level of (roslisp top) would be looked up. If this is not present (roslisp) is looked up. If this is not present, () is looked up (and this is always present in the topic list). The level at runtime then determines whether the message is evaluated and outputted (to stdout and rosout).

To set debug levels, from within Lisp use set-debug-levels. To produce debugging output, use ros-{debug|info|warn|error|fatal}. Additionally, debug levels correspond to ros parameters, e.g., topic (foo bar) corresponds to the private parameter ~debug/foo/bar/level. Upon node initialization, these are read from the parameter server, and must be one of the five strings debug, info, warn, error, or fatal. If they are changed after node startup, call the node's ~reset-debug-levels service to update. A more permanent way to update debug levels is to call set-debug-levels in an initialization file.

Roslisp itself uses debugging levels starting with :roslisp, with subtopics such as :top, :tcp, and :rosout. For example, if debugging roslisp_examples/bin/talker, add the following line to roslisp_examples/bin/roslisp-init.lisp:

(roslisp:set-debug-levels roslisp :debug)

To reduce the number of connection-related debugging messages, also add the line

(roslisp:set-debug-levels (roslisp tcp) :info)


The functions in the client API below belong to the Lisp package (namespace) named :roslisp, with the exception of the constructors and field accessors for ROS message data types, which belong to a Lisp package with the same name as the message's ROS package concatenated with "-msg" (and likewise for services, with the suffix "-srv").


Names (of topics, services, and parameters) are handled according to standard ROS conventions. Command-line arguments to the executable, of the form foo:=bar, where foo does not begin with '_', are known as command line remappings. Given such a remapping, any topic, parameter, or service referred to as foo in the node's code would then be replaced by bar. The node name is given by the argument to start-ros-node or with-ros-node. It can, however, be overridden by including a command-line argument of the form __name=foo. The namespace is set as follows: if there is a command-line argument __ns:=foo, the namespace is foo. If not, and if the environment variable ROS_NAMESPACE is set to bar, the namespace is bar. If not, the namespace is /. All commands below that take a name of a topic, service, or parameter can be given an absolute (/foo/bar/baz), relative (baz/qux), or private (~qux) name.

Starting and stopping a node

See documentation for functions start-ros-node, shutdown-ros-node, and with-ros-node.


See functions advertise, subscribe, publish, publish-msg.


See functions call-service, def-service-callback, register-service, register-service-fn, wait-for-service, make-request.


See functions get-param, set-param, has-param, delete-param.

Node information

See function node-status.

Miscellaneous functions

See make-uri, fully-qualified-name, loop-at-most-every, ros-time,

Message data types

Each ROS message type has a corresponding Lisp class and operations on it. A message type foo in ROS package bar corresponds to a Lisp class named <foo> in the bar-msg Lisp package. If your code will create or operate on objects of this type, it should contain the form (roslisp:load-message-types "bar/foo"). Operations in the message's package:

  • An object of type <foo> in package bar-msg, with initial value of field baz equal to 3, is created using (make-instance 'bar-msg:<foo> :baz 3).
  • Given a field named baz in an object m of the above message type, it can be read using (bar-msg:baz-val m).

However, it is recommended that you use the list operations below such as with-fields, unless this is slowing your code down.

The roslisp Lisp package contains some additional generic operations that work on any message:

  • symbol-code M S. M is either a message or the name of a message class. S is a keyword symbol naming a constant declaration in the .msg file. Returns the value of the constant. For example, to get the value of the DEBUG constant in roslib/Log.msg, use (symbol-code 'roslib-msg:<Log> :debug) or (symbol-code m :debug) where m is an instance of '<Log>.
  • ros-message-to-list MSG
  • list-to-ros-message L
  • pprint-ros-message STREAM MSG prints the message to the given stream in human-readable format. This is also set as the default dispatch function for ROS messages in Lisp's pretty printer. So if you have pretty printing turned on, and call a function from the prompt that returns a ROS message, that return value will be printed human-readably using pprint-ros-message. Similarly, if your code contains something like (format t "The message is ~a" m), that will DTRT.

There are a few additional operations that use the list representation of ros messages, and are therefore less efficient, but more readable and convenient for interactive use. See with-fields, make-message, modify-message-copy, and setf-msg.

IMPORTANT: message objects are assumed to be immutable; this assumption may be used in future to cache various things. In other words, if m is a variable that refers to some message object, don't do something like (setf (slot-value m 'my-field) 42). Instead, in this situation, do something like (setf-msg m 'my-field 42) (of course, it's always legal to do something like (setq m (function-that-returns-new-message-object)) since that just changes what m refers to rather than modifying the pointed-to object). When constructing messages, either use the form (make-instance '<Foo> :field1 42 :field24) or (make-msg "my_package/Foo" :field1 42 :field2 24). Don't use the C++-inspired way of first creating the object then setting its fields.

Service Data Types

Given a ROS service type qux in the bar ROS package, there are corresponding message types <qux-request> and <qux-response> in the bar-srv Lisp package. The request and response messages can be operated on like any other message.

Author(s): Bhaskara Marthi, Brian Gerkey, Lorenz Moesenlechner , Thibault Kruse
autogenerated on Fri Feb 17 2023 03:23:17