Documentation
LISPCL is a Lisp client for the Player project. It is written completeley in Lisp and doesn't make use of any C library. The implementation supports all interfaces of Player 2.x, except the deprecated ones. For the interfacesblobfinder
, laser
, planner
, position2d
, position3d
, ptz
, and sonar
wrapper methods for sending commands and requests are provided. The other interfaces are supported by the direct usage of the methods proxy-command
and proxy-request
. The supported Lisp implementations are AllegroCL, CMUCL, SBCL, and CLISP. Threads are supported for AllegroCL and CMUCL.
Installation
-
LISPCL uses asdf (Another System Definition Facility) to load its files. No other dependency exists. Make sure asdf is loaded.
(load "/path/to/asdf.lisp")
or(require 'asdf)
- Untar LISPCL's current version which creates a directory for the LISPCL files.
-
Add this directory to the asdf variable
asdf:*central-registry*
by pushing the directory onto the list.
(push #"/path/to/lispcl-2.x.x-x/" asdf:*central-registry*)
-
Load LISPCL:
(asdf:operate 'asdf:load-op :lispcl)
-
Or load the LISPCL tests and examples (this will also load the other LISPCL files).
(asdf:operate 'asdf:load-op :lispcl-test)
An example for my configuration files .clinit.cl
, .cmucl-init.lisp
, .sbclrc
, and .clisprc
can be found here.
Test LISPCL
After having installed and loaded LISPCL (lispcl-test.asd
) change to the package LISPCL (in-package "LISPCL")
and start the Player server, e.g. player space-wanderer.cfg
(see next section). The connection to the Player server can be established either with (pc-test-start)
(non-threaded version) or with (pc-threaded-test-start)
(threaded version). This will connect to all available interfaces provided by the Player server. In the non-threaded case you have to read new data manually by calling (read-data (pc-get))
. Disconnection is achieved with (pc-test-stop)
. During the connection you can send commands and requests and check the received data (see section Usage for more detail). Here are some examples:
-
Get player client instance:
(pc-get)
-
Get
blobfinder
,laser
,planner
,position2d
,position3d
,ptz
, orsonar
proxy at indexix
:(bp-get ix)
(lp-get ix)
(plp-get ix)
(p2dp-get ix)
(p3dp-get ix)
(ptzp-get ix)
(sp-get ix)
-
Get
position2d
proxy data:
(get-data (p2dp-get 0) *player-position2d-data-state*)
-
Set
position2d
proxy velocity command:
(set-velocity (p2dp-get 0) :x 0.2 :az 0.5)
An example test session can be found here.
Examples
The examples were originally written by Radu Bogdan Rusu as Java-Client examples. These examples have been rewritten in Lisp to demonstrate LISPCL. To use these examples you have to load lispcl-test.asd
(see Installation). The configuration files for player are located in the examples
directory.
Space Wanderer Example
The example shows a basic Space Wanderer algorithm for a Pioneer-like mobile robot with 8 sonars.
-
Start player/stage:
player space-wanderer.cfg
-
Change the package:
(in-package "LISPCL")
-
Start the non-threaded version for 60 seconds:
(space-wanderer)
-
Start the threaded version:
(space-wanderer :threaded T)
-
Stop threaded version:
(pc-test-stop)
-
The non-threaded version accepts the keyword argument
:timeout
to alter the duration in seconds:
(space-wanderer :timeout 120)
Wall Follower example
The example shows a very simple implementation of a wall following behavior by using only the information from the left and front sonar sensors.
-
Start player/stage:
player wall-follower.cfg
-
Change the package:
(in-package "LISPCL")
-
Start the wall follower for 60 seconds:
(wall-follower)
-
Optionally the keyword argument
:timeout
can be given in seconds:
(wall-follower :timeout 300)
Blob Finder examples
A basic example on how to use the blobfinder
interface together with Stage for a Pioneer-like mobile robot. The robot navigates around using the basic Space Wanderer algorithm.
-
Start player/stage:
player blob-finder.cfg
-
Change the package:
(in-package "LISPCL")
-
Start the non-threaded version for 60 seconds:
(blob-finder)
-
Start the threaded version:
(blob-finder :threaded T)
-
Stop threaded version:
(pc-test-stop)
-
The non-threaded version accepts the keyword argument
:timeout
to alter the duration in seconds:
(blob-finder :timeout 120)
Usage
For examples on how to use LISPCL in your project please look at the source code in tests-examples.lisp
. Here some remarks on the implementation of LISPCL and hints for using LISPCL are provided. Code examples in this section assume that you are in the package LISPCL
, otherwise add the package name to the symbols, e.g. lispcl:player-client
. All constants, classes, and methods are exported. The example code snippets of this section can be found here.
Basics
LISPCL is written completeley in Lisp and doesn't make use of any C library. Particulary the C client library and the XDR conversion library provided by Player are not used. Instead the same approach as in Player is used. The file player.h
is parsed and the following three files are generated:
-
constants-player.lisp
:
Definition of the Player constants. In the names all occurences of '_' are replaced with '-' and '*' is added as prefix and suffix, e.g.PLAYER_POSITION2D_DATA_STATE
becomes*player-position2d-data-state*
. -
xdr-player.lisp
:
Definition of the Player data, command, and request structures as Lisp classes and definition of the XDR conversion methodsxdr-read
andxdr-write
for each class. In the names of the classes and the slots again all occurences of '_' are replaced with '-'. The reader and writer methods of the slots have the additional prefix 'player-
', e.g.(player-px (player-pos (make-instance 'player-position2d-data)))
. -
proxies-player.lisp
:
Definition of the Player proxy classes. The class name follows the rule<interface-name>-proxy
, e.g.position2d-proxy
.
Connecting to Player Server
A connection to the Player server is established by creating an instance of the class player-client
, e.g. (setf pc (make-instance 'player-client))
. The following keyword arguments are accepted:
-
:host
:
Host to connect to (default:"localhost"
) -
:port
:
Port to connect to (default:6665
) -
:thread-fun
:
In threaded mode the function reading messages can be given here (default:nil
). An example of such a function ispc-test-read-run
defined intests-examples.lisp
.
After being connected to the Player server it is possible to change the data mode to PULL or PUSH and to add replace rules, e.g.:
(set-datamode (get-player-proxy pc) *player-datamode-pull*)
(set-replace-rule (get-player-proxy pc) -1 -1 *player-msgtype-data* -1 T)
A connection to a specific interface is established by creating an instance of the according proxy class, providing the keyword arguments :player-client
(the previously created instance) and :index
(index of interface), e.g (make-instance 'position2d-proxy :player-client pc :index 0)
If the proxy class hasn't been saved in a local variable, it can always be retrieved with the method get-proxy
, e.g. (setf p2dp (get-proxy pc *player-position2d-code* 0))
.
Receiving Data
In non-threaded mode new data has to be read manually. This is done with (read-data pc)
. In PUSH mode only one message is read. In PULL mode a new round of data is requested and read.
In threaded mode all messages are read by the thread-fun
specified when connecting to the Player server. See pc-test-read-run
defined in tests-examples.lisp
for more detail. In PULL mode this function assumes that the user requests the first round of data manually (request-data (get-player-proxy pc))
. Afterwards new rounds of data are automatically requested.
The last received data state can be accessed with the method get-data
, e.g. (get-data p2dp *player-position2d-data-state*)
.
The easiest way to react to new data, is to attach a data handler to each data message type. A data handler is called whenever a new data message is received.
-
Set data handler:
(set-data-handler p2dp *player-position2d-data-state* #'(lambda (proxy data) (format T "New data: ~a: ~a~%" (type-of proxy) data)))
-
Remove data handler:
(set-data-handler p2dp *player-position2d-data-state* nil)
-
Get current data handler:
(get-data-handler p2dp *player-position2d-data-state*)
Sending Commands and Requests
For the proxies blobfinder
, laser
, planner
, position2d
, position3d
, ptz
, and sonar
wrapper methods for sending commands and requests are provided. For method names and arguments please refer to the source code. New wrapper methods will follow and requests for or new implementations of new methods are welcomed. Please use the mailing list or the appropriate Sourceforge tracker.
-
Set robot velocity:
(set-velocity p2dp :x 0.2 :az 0.5)
-
Stop robot:
(set-velocity p2dp)
-
Get robot geometry:
(get-geometry p2dp)
By using the methods proxy-command
and proxy-request
it is possible to send commands and requests to other interfaces. Please refer to the Player manual for supported commands and requests.
-
Set robot velocity:
(proxy-command p2dp *player-position2d-cmd-vel* (make-instance 'player-position2d-cmd-vel :vel (make-instance 'player-pose :px 0.2 :py 0.0 :pa 0.5) :state 1))
-
Stop robot:
(proxy-command p2dp *player-position2d-cmd-vel* (make-instance 'player-position2d-cmd-vel :vel (make-instance 'player-pose :px 0.0 :py 0.0 :pa 0.0) :state 1))
-
Get robot geometry:
(proxy-request p2dp *player-position2d-req-get-geom* nil :response (make-instance 'player-position2d-geom))
-
Set motor state of robot:
(proxy-request p2dp *player-position2d-req-motor-power* (make-instance 'player-position2d-power-config :state 1))
Disconnecting from Player Server
Disconnection is done with the method disconnect
. This method accepts either the player client instance (all proxies are disconnected and then the connection to the server is closed) or a proxy instance (only the proxy is disconnected), e.g. (disconnect p2dp)
or (disconnect pc)
.
Supported Lisp Implementations/Platforms
- AllegroCL (v8.0, Linux x86, Linux AMD64, threaded/non-threaded)
- CMUCL (19d, Linux x86, threaded/non-threaded)
- SBCL (0.9.16, Linux x86, non-threaded)
- CLISP (2.41, Linux x86, non-threaded)
For other successfully tested Lisp implementations/platforms please send e-mail to the mailing list.