PIC

The Urbi Software Development Kit


Version 2.7.5
Gostai

July 26, 2011
(Revision 2.7.5)

Urbi is an open source robotics software platform. It is cross-platform: it supports several robots (Gostai Jazz, Segway RMP, Pioneer 3-DX, LEGO Mindstorms NXT, Aldebaran Nao…) and simulators (Webots…). It runs on top of all the major operating systems. It features a C++/Java middleware, UObject, to interface components such as motors, cameras, and algorithms; and an innovative scripting language, urbiscript, with built-in support for parallel and event-based programming. It is compatible with ROS, the Robotic Operating System.
PIC

Chapter 1
Introduction

Urbi SDK is a fully-featured environment to orchestrate complex organizations of components. It is an open source framework for robotics and other complex systems. It relies on a middleware architecture that coordinates components named UObjects. It also features urbiscript, a scripting language tailored to write orchestration programs.

 1.1 Urbi and UObjects
 1.2 The Big Picture
 1.3 Urbi and urbiscript
 1.4 Genesis
 1.5 Outline
 1.6 Documentation

1.1 Urbi and UObjects

Urbi makes the orchestration of independent and concurrent components easier. It was first designed for robotics: it provides all the needed features to coordinate the execution of various components (actuators, sensors, software devices that provide features such as text-to-speech, face recognition and so forth). Languages such as C++ are well suited to program the local, low-level, handling of these hardware or software devices; indeed one needs efficiency, small memory footprint, and access to low-level hardware details. Yet, when it comes to component orchestration and coordination, in a word, when it comes to addressing concurrency, it can be tedious to use such languages.

Middleware infrastructures make possible to use remote components as if they were local, to allow concurrent execution, to make synchronous or asynchronous requests and so forth. The UObject C++ architecture provides exactly this: a common API that allows conforming components to be used seamlessly in highly concurrent settings. Components need not be designed with UObjects in mind, rather, UObjects are typically “shells” around “regular” components.

Components with an UObject interface are naturally supported by the urbiscript programming language. This provides a tremendous help: one can interact with these components (making queries, changing them, observing their state, monitoring various kinds of events and so forth), which provides a huge speed-up during development.

Although made with robots in mind, the UObject architecture is well suited to tame any heavily concurrent environment, such as video games or complex systems in general.

1.2 The Big Picture

The Section 1.1 shows the architecture of Urbi. Let’s browse it bottom up.


PIC

Figure 1.1: A Bird-View of the Urbi Architecture

At the lowest level, Urbi requires a (possibly very limited) embedded computer. This is the case for most robots today, but on occasion, some device cannot even run reasonably small pieces of code. In that case, Urbi can still be used, but then the robot is actually remote-controlled from a computer running Urbi.

Right on top of the hardware, is running the Operating System. Urbi supports the major OSes; it was also ported on top of real-time OSes such as Xenomai, and on specific OSes such as Aperios, Sony’s proprietary system running its Aibo robotic dog.

The Urbi Runtime, which is the actual core of the system, also known as the engine or the kernel, is interfacing the OS with the rest of the Urbi world, urbiscript and UObjects.

UObjects are used to bind hardware or software components, such as actuators and sensors on the one hand, and voice synthesis or face recognition on the other hand. They can be run locally on the robot, or on a remote, more powerful, computer.

To orchestrate all the components, urbiscript is a programming language of choice (see below).

Finally, applications are available for the Urbi environment. For instance, Gostai Studio provides high-level tools to develop complex robotic behaviors.

1.3 Urbi and urbiscript

urbiscript is a programming language primarily designed for robotics. It’s a dynamic, prototype-based, object-oriented scripting language. It supports and emphasizes parallel and event-based programming, which are very popular paradigms in robotics, by providing core primitives and language constructs.

Its main features are:

1.4 Genesis

Urbi what first designed and implemented by Jean-Christophe Baillie, together with Matthieu Nottale. Because its users wildly acclaimed it, Jean-Christophe founded Gostai, a France-based Company that develops software for robotics with a strong emphasis on personal robotics.

Authors Urbi SDK 1 was further developed by Akim Demaille, Guillaume Deslandes, Quentin Hocquet, and Benoît Sigoure.

The Urbi SDK 2 project was started and developed by Akim Demaille, Quentin Hocquet, Matthieu Nottale, and Benoît Sigoure. Samuel Tardieu provided an immense help during the year 2008, in particular for the concurrency and event support.

The maintenance is currently carried out by Akim Demaille, Quentin Hocquet, and Matthieu Nottale. Jean-Christophe Baillie is still deeply involved in the development of urbiscript, he regularly submits ideas, and occasionally even code!

Contributors Many people contributed significantly to Urbi, including Alexandre Morgand, Romain Bezut, Thomas Moulard, Clément Moussu, Nicolas Pierron.

1.5 Outline

This multi-part document provides a complete guide to Urbi. See Chapter 34 for the various notations that are used in the document.

Part I Urbi and UObjects User Manual
 
This part covers the Urbi architecture: its core components (client/server architecture), how its middleware works, how to include extensions as UObjects (C++ components) and so forth.

No knowledge of the urbiscript language is needed. As a matter of fact, Urbi can be used as a standalone middleware architecture to orchestrate the execution of existing components.

Yet urbiscript is a feature that “comes for free”: it is easy using it to experiment, prototype, and even program fully-featured applications that orchestrate native components. The interested reader should read either the urbiscript user manual (Part II), or the reference manual (Chapter 22).

  Chapter 3 Quick Start
 
This chapter, self-contained, shows the potential of Urbi used as a middleware.
  Chapter 4 The UObject API
 
This section shows the various steps of writing an Urbi C++ component using the UObject API.
  Chapter 5 The UObject Java API
 
UObjects can also be written in Java. This section demonstrates it all.
  Chapter 6 Use Cases
 
Interfacing a servomotor device as an example on how to use the UObject architecture as a middleware.
Part II urbiscript User Manual  
This part, also known as the “urbiscript tutorial”, teaches the reader how to program in urbiscript. It goes from the basis to concurrent and event-based programming. No specific knowledge is expected. There is no need for a C++ compiler, as UObject will not be covered here (see Part I). The reference manual contains a terse and complete definition of the Urbi environment (Part IV).
  Chapter 7 First Steps
 
First contacts with urbiscript.
  Chapter 8 Basic Objects, Value Model
 
A quick introduction to objects and values.
  Chapter 9 Flow Control Constructs
 
Basic control flow: if, for and the like.
  Chapter 10 Advanced Functions and Scoping
 
Details about functions, scopes, and lexical closures.
  Chapter 11 Objective Programming, urbiscript Object Model
 
A more in-depth introduction to object-oriented programming in urbiscript.
  Chapter 12 Functional Programming
 
Functions are first-class citizens.
  Chapter 13 Parallelism, Concurrent Flow Control
 
The urbiscript operators for concurrency, tags.
  Chapter 14 Event-based Programming
 
Support for event-driven concurrency in urbiscript.
  Chapter 15 Urbi for ROS Users
 
How to use ROS from Urbi, and vice-versa.
Part III Guidelines and Cook Books  
This part contains guides to some specific aspects of Urbi SDK.
  Chapter 16 Installation
 
Complete instructions on how to install Urbi SDK.
  Chapter 17 Frequently Asked Questions
 
Some answers to common questions.
  Chapter 18 Urbi Guideline
 
Based on our own experience, and code that users have submitted to us, we suggest a programming guideline for Urbi SDK.
  Chapter 19 Migration from urbiscript 1 to urbiscript 2
 
This chapter is intended to people who want to migrate programs in urbiscript 1 to urbiscript 2.
  Chapter 20 Building Urbi SDK
 
Building Urbi SDK from the sources. How to install it, how to check it and so forth.
Part IV Urbi SDK Reference Manual  
This part defines the specifications of the urbiscript language. It defines the expected behavior from the urbiscript interpreter, the standard library, and the SDK. It can be used to check whether some code is valid, or browse urbiscript or C++ API for a desired feature. Random reading can also provide you with advanced knowledge or subtleties about some urbiscript aspects.

This part is not an urbiscript tutorial; it is not structured in a progressive manner and is too detailed. Think of it as a dictionary: one does not learn a foreign language by reading a dictionary. For an urbiscript Tutorial, see Part II.

This part does not aim at giving advanced programming techniques. Its only goal is to define the language and its libraries.

  Chapter 21 Programs
 
Presentation and usage of the different tools available with the Urbi framework related to urbiscript, such as the Urbi server, the command line client, umake, …
  Chapter 22 urbiscript Language Reference Manual
 
Core constructs of the language and their behavior.
  Chapter 23 urbiscript Standard Library
 
Listing of all classes and methods provided in the standard library.
  Chapter 24 Communication with ROS
 
Urbi provides a set of tools to communicate with ROS (Robot Operating System). For more information about ROS, see http://www.ros.org. Urbi, acting as a ROS node, is able to interact with the ROS world.
  Chapter 25 Gostai Standard Robotics API
 
Also known as “The Urbi Naming Standard”: naming conventions in for standard hardware/software devices and components implemented as UObject and the corresponding slots/events to access them.
Part V Urbi Platforms  
This part covers the specific features of Urbi for some of the platforms it was ported to. Environments not described in this part are covered in separate, stand-alone, documentations.
  Chapter 26 Aldebaran Nao
 
Nao is a humanoid robot Nao from Aldebaran Robotics.
  Chapter 27 Bioloid
 
Using the Bioloid robot construction kit with Urbi.
  Chapter 28 Mindstorms NXT
 
LEGO Mindstorms NXT is a programmable robotics kit released by Lego in July 2006, replacing the first-generation LEGO Mindstorms kit. The kit consists of 519 Technic pieces, 3 servo motors, 4 sensors (ultrasonic, sound, touch, and light), 7 connection cables, a USB interface cable, and the NXT Intelligent Brick.
  Chapter 29 Gostai Open Jazz
 
Gostai Open Jazz is an entirely programmable robot. It is shipped with the Urbi SDK to develop with Jazz.
  Chapter 30 Pioneer 3-DX
 
Pioneer 3-DX8 is an agile, versatile intelligent mobile robotic platform updated to carry loads more robustly and to traverse sills more surely with high-performance current management to provide power when it’s needed.
  Chapter 31 Segway RMP
 
The Segway Robotic Mobility Platform is a robotic platform based on the Segway Personal Transporter.
  Chapter 32 Spykee
 
The Spykee is a WiFi-enabled robot built by Meccano (known as Erector in the United States). It is equipped with a camera, speaker, microphone, and moves using two tracks.
  Chapter 33 Webots
 
Using Cyberbotics’ Webots simulation environment with Urbi.
Part VI Tables and Indexes  
This part contains material about the document itself.
  Chapter 34 Notations
 
Conventions used in the type-setting of this document.
  Chapter 35 Release Notes
 
Release notes of Urbi SDK.
  Chapter 36 Licenses
 
Licenses of components used in Urbi SDK.
  Chapter 37 ł::bel sec:bibliographyBibliography
 
References to other documents such as documentation, scientific papers, etc.
  Chapter 38 Glossary
 
Definition of the terms used in this document.
  Chapter 39 List of Tables
 
Index of all the tables: list of keywords, operators, etc.
  Chapter 40 List of Figures
 
Index of all the figures: snapshots, schema, etc.
  ?? ??
 
An index of concepts, objects, and some selected routines.

1.6 Documentation

You may want to look at the documentation of the latest version, and visit http://urbiforge.org, the Urbi community web site, and its forum.

This document and others are updated regularly on the Gostai Web site:

Contents

1 Introduction
 1.1 Urbi and UObjects
 1.2 The Big Picture
 1.3 Urbi and urbiscript
 1.4 Genesis
 1.5 Outline
 1.6 Documentation
2 Getting Started
I  Urbi and UObjects User Manual
3 Quick Start
 3.1 UObject Basics
  3.1.1 The Objects to Bind into Urbi
  3.1.2 Wrapping into an UObject
  3.1.3 Running Components
   3.1.3.1 Compiling
   3.1.3.2 Running UObjects
 3.2 Using urbiscript
  3.2.1 The urbiscript Scripting Language
  3.2.2 Concurrency
   3.2.2.1 First Attempt
   3.2.2.2 Second Attempt: Threaded Functions
 3.3 Conclusion
4 The UObject API
 4.1 Compiling UObjects
  4.1.1 Compiling by hand
  4.1.2 The umake-* family of tools
  4.1.3 Using the Visual C++ Wizard
 4.2 Creating a class, binding variables and functions
 4.3 Creating new instances
 4.4 Binding functions
  4.4.1 Simple binding
  4.4.2 Multiple bindings
  4.4.3 Asynchronous binding
 4.5 Notification of a variable change or access
  4.5.1 Threaded notification
 4.6 Data-flow based programming: exchanging UVars
 4.7 Data-flow based programming: InputPort
  4.7.1 Customizing data-flow links
 4.8 Timers
 4.9 The special case of sensor/actuator variables
 4.10 Using Urbi variables
 4.11 Emitting events
 4.12 UObject and Threads
 4.13 Using binary types
  4.13.1 UVar conversion and memory management
  4.13.2 Binary conversion
  4.13.3 0-copy mode
 4.14 Direct Communication between UObjects
 4.15 Using hubs to group objects
 4.16 Sending urbiscript code
 4.17 Using RTP transport in remote mode
  4.17.1 Enabling RTP
  4.17.2 Per-UVar control of RTP mode
 4.18 Extending the cast system
  4.18.1 Principle
  4.18.2 Casting simple structures
5 The UObject Java API
 5.1 Compiling and running UObjects
  5.1.1 Compiling and running by hand
  5.1.2 The umake-java and urbi-launch-java tools
 5.2 Creating a class, binding variables and functions
 5.3 Creating new instances
 5.4 Binding functions
  5.4.1 Simple binding
 5.5 Notification of a variable change or access
 5.6 Timers
 5.7 Using Urbi variables
 5.8 Sending Urbi code
 5.9 Providing a main class or not
 5.10 Import the examples with Eclipse
 5.11 Run the UObject Java examples
6 Use Cases
 6.1 Writing a Servomotor Device
  6.1.1 Caching
  6.1.2 Using Timers
 6.2 Using Hubs to Group Objects
  6.2.1 Alternate Implementation
 6.3 Writing a Camera Device
  6.3.1 Optimization in Plugin Mode
 6.4 Writing a Speaker or Microphone Device
 6.5 Writing a Softdevice: Ball Detection
II  urbiscript User Manual
7 First Steps
 7.1 Comments
 7.2 Literal values
 7.3 Function calls
 7.4 Variables
 7.5 Scopes
 7.6 Method calls
 7.7 Function definition
 7.8 Conclusion
8 Basic Objects, Value Model
 8.1 Objects in urbiscript
 8.2 Methods
 8.3 Everything is an object
 8.4 The urbiscript values model
 8.5 Conclusion
9 Flow Control Constructs
 9.1 if
 9.2 while
 9.3 for
 9.4 switch
 9.5 do
10 Advanced Functions and Scoping
 10.1 Scopes as expressions
 10.2 Advanced scoping
 10.3 Local functions
 10.4 Lexical closures
11 Objective Programming, urbiscript Object Model
 11.1 Prototype-Based Programming in urbiscript
 11.2 Prototypes and Slot Lookup
 11.3 Copy on Write
 11.4 Defining Pseudo-Classes
 11.5 Constructors
 11.6 Operators
 11.7 Properties
  11.7.1 Features of Values
  11.7.2 Features of Slots
12 Functional Programming
 12.1 First class functions
 12.2 Lambda functions
 12.3 Lazy arguments
13 Parallelism, Concurrent Flow Control
 13.1 Parallelism operators
 13.2 Detach
 13.3 Tags for parallel control flows
 13.4 Advanced example with parallelism and tags
14 Event-based Programming
 14.1 Watchdog constructs
 14.2 Events
  14.2.1 Emitting Events
  14.2.2 Emitting events with a payload
15 Urbi for ROS Users
 15.1 Communication on topics
  15.1.1 Starting a process from Urbi
  15.1.2 Listening to Topics
  15.1.3 Advertising on Topics
   15.1.3.1 Simple Talker
   15.1.3.2 Turtle Simulation
 15.2 Using Services
 15.3 Image Publisher from ROS to Urbi
 15.4 Image Subscriber from Urbi to ROS
 15.5 Remote communication
III  Guidelines and Cook Books
16 Installation
 16.1 Download
 16.2 Install & Check
  16.2.1 GNU/Linux and Mac OS X
  16.2.2 Windows
17 Frequently Asked Questions
 17.1 Build Issues
  17.1.1 Complaints about ‘+=
  17.1.2 error: ‘<anonymous>’ is used uninitialized in this function
  17.1.3 AM_LANGINFO_CODESET
  17.1.4 configure: error: The Java VM java failed
  17.1.5 make check’ fails
 17.2 Troubleshooting
  17.2.1 error while loading shared libraries: libport.so
  17.2.2 Error 1723: “A DLL required for this install to complete could not be run.”
  17.2.3 When executing a program, the message “The system cannot execute the specified program.” is raised.
  17.2.4 When executing a program, the message “This application has failed to start” is raised.
  17.2.5 The server dies with “stack exhaustion”
  17.2.6 ’myuobject: file not found’. What can I do?
 17.3 urbiscript
  17.3.1 Objects lifetime
  17.3.2 Slots and variables
  17.3.3 Tags
  17.3.4 Events
  17.3.5 Standard Library
 17.4 UObjects
  17.4.1 Is the UObject API Thread-Safe?
 17.5 Miscellaneous
  17.5.1 What has changed since the latest release?
  17.5.2 How can I contribute to the code?
  17.5.3 How do I report a bug?
18 Urbi Guideline
 18.1 urbiscript Programming Guideline
  18.1.1 Prefer Expressions to Statements
  18.1.2 Avoid return
19 Migration from urbiscript 1 to urbiscript 2
 19.1 $(Foo)
 19.2 delete Foo
 19.3 emit Foo
 19.4 eval(Foo)
 19.5 foreach
 19.6 group
 19.7 loopn
 19.8 new Foo
 19.9 self
 19.10 stop Foo
 19.11 # line
 19.12 tag+end
20 Building Urbi SDK
 20.1 Requirements
  20.1.1 Bootstrap
  20.1.2 Build
  20.1.3 Check
 20.2 Check out
 20.3 Bootstrap
 20.4 Configure
  20.4.1 configuration options
  20.4.2 Windows: Cygwin
  20.4.3 Building For Windows
  20.4.4 Building for Windows using Cygwin
 20.5 Compile
 20.6 Install
 20.7 Relocatable
 20.8 Run
 20.9 Check
  20.9.1 Lazy test suites
  20.9.2 Partial test suite runs
IV  Urbi SDK Reference Manual
21 Programs
 21.1 Environment Variables
  21.1.1 Search Path Variables
  21.1.2 Environment Variables
 21.2 Special Files
 21.3 urbi — Running an Urbi Server
  21.3.1 Options
  21.3.2 Quitting
 21.4 urbi-image — Querying Images from a Server
  21.4.1 Options
 21.5 urbi-launch — Running a UObject
  21.5.1 Invoking urbi-launch
  21.5.2 Examples
 21.6 urbi-launch-java — Running a Java UObject
  21.6.1 Invoking urbi-launch-java
 21.7 urbi-ping — Checking the Delays with a Server
  21.7.1 Options
 21.8 urbi-send — Sending urbiscript Commands to a Server
 21.9 urbi-sound — Querying Sounds from a Server
  21.9.1 Options
 21.10 umake — Compiling UObject Components
  21.10.1 Invoking umake
  21.10.2 umake Wrappers
22 urbiscript Language Reference Manual
 22.1 Syntax
  22.1.1 Characters, encoding
  22.1.2 Comments
  22.1.3 Synclines
  22.1.4 Identifiers
  22.1.5 Keywords
  22.1.6 Literals
   22.1.6.1 Angles
   22.1.6.2 Dictionaries
   22.1.6.3 Durations
   22.1.6.4 Floats
   22.1.6.5 Lists
   22.1.6.6 Strings
   22.1.6.7 Tuples
   22.1.6.8 Pseudo classes
  22.1.7 Statement Separators
   22.1.7.1 ;
   22.1.7.2 ,
   22.1.7.3 |
   22.1.7.4 &
  22.1.8 Operators
   22.1.8.1 Arithmetic operators
   22.1.8.2 Assignment operators
   22.1.8.3 Postfix Operators
   22.1.8.4 Bitwise operators
   22.1.8.5 Logical operators
   22.1.8.6 Comparison operators
   22.1.8.7 Container operators
   22.1.8.8 Object operators
   22.1.8.9 All operators summary
 22.2 Scopes and local variables
  22.2.1 Scopes
  22.2.2 Local variables
 22.3 Functions
  22.3.1 Function Definition
  22.3.2 Arguments
  22.3.3 Return value
  22.3.4 Call messages
  22.3.5 Strictness
  22.3.6 Lexical closures
  22.3.7 Variadic functions
 22.4 Objects
  22.4.1 Slots
   22.4.1.1 Manipulation
   22.4.1.2 Syntactic Sugar
  22.4.2 Properties
   22.4.2.1 Manipulation
   22.4.2.2 Standard Properties
  22.4.3 Prototypes
   22.4.3.1 Manipulation
   22.4.3.2 Inheritance
   22.4.3.3 Copy on write
  22.4.4 Sending messages
 22.5 Enumeration types
 22.6 Structural Pattern Matching
  22.6.1 Basic Pattern Matching
  22.6.2 Variable
  22.6.3 Guard
 22.7 Imperative flow control
  22.7.1 break
  22.7.2 continue
  22.7.3 do
  22.7.4 if
  22.7.5 for
   22.7.5.1 C-like for
   22.7.5.2 Range-for
   22.7.5.3 for n-times
  22.7.6 if
  22.7.7 loop
  22.7.8 switch
  22.7.9 while
   22.7.9.1 while;
   22.7.9.2 while—
 22.8 Exceptions
  22.8.1 Throwing exceptions
  22.8.2 Catching exceptions
  22.8.3 Inspecting exceptions
  22.8.4 Finally
   22.8.4.1 Regular execution
   22.8.4.2 Control-flow
   22.8.4.3 Exceptions
 22.9 Assertions
  22.9.1 Asserting an Expression
  22.9.2 Assertion Blocks
 22.10 Parallel and event-based flow control
  22.10.1 at
   22.10.1.1 at on Events
   22.10.1.2 at on Boolean Expressions
   22.10.1.3 Synchronous and asynchronous at
   22.10.1.4 Scoping at at
  22.10.2 every
   22.10.2.1 every|
  22.10.3 watch
   22.10.3.1 every,
  22.10.4 for
   22.10.4.1 C-for,
   22.10.4.2 range-for& (:)
   22.10.4.3 for& (n)
  22.10.5 loop,
  22.10.6 waituntil
   22.10.6.1 waituntil on Events
   22.10.6.2 waituntil on Boolean Expressions
  22.10.7 whenever
   22.10.7.1 whenever on Events
   22.10.7.2 whenever on Boolean Expressions
  22.10.8 While
   22.10.8.1 while,
 22.11 Trajectories
 22.12 Garbage collection and limitations
23 urbiscript Standard Library
 23.1 Barrier
  23.1.1 Prototypes
  23.1.2 Construction
  23.1.3 Slots
 23.2 Binary
  23.2.1 Prototypes
  23.2.2 Construction
  23.2.3 Slots
 23.3 Boolean
  23.3.1 Prototypes
  23.3.2 Construction
  23.3.3 Truth Values
  23.3.4 Slots
 23.4 CallMessage
  23.4.1 Examples
   23.4.1.1 Evaluating an argument several times
   23.4.1.2 Strict Functions
  23.4.2 Slots
 23.5 Channel
  23.5.1 Prototypes
  23.5.2 Construction
  23.5.3 Slots
 23.6 Code
  23.6.1 Prototypes
  23.6.2 Construction
  23.6.3 Slots
 23.7 Comparable
  23.7.1 Slots
 23.8 Container
  23.8.1 Prototypes
  23.8.2 Slots
 23.9 Control
  23.9.1 Prototypes
  23.9.2 Slots
 23.10 Date
  23.10.1 Prototypes
  23.10.2 Construction
  23.10.3 Slots
 23.11 Dictionary
  23.11.1 Example
  23.11.2 Hash values
  23.11.3 Prototypes
  23.11.4 Construction
  23.11.5 Slots
 23.12 Directory
  23.12.1 Prototypes
  23.12.2 Construction
  23.12.3 Slots
 23.13 Duration
  23.13.1 Prototypes
  23.13.2 Construction
  23.13.3 Slots
 23.14 Enumeration
  23.14.1 Prototypes
  23.14.2 Examples
  23.14.3 Construction
  23.14.4 Slots
 23.15 Event
  23.15.1 Prototypes
  23.15.2 Examples
  23.15.3 Construction
  23.15.4 Slots
 23.16 Exception
  23.16.1 Prototypes
  23.16.2 Construction
  23.16.3 Slots
  23.16.4 Specific Exceptions
 23.17 Executable
  23.17.1 Prototypes
  23.17.2 Construction
  23.17.3 Slots
 23.18 File
  23.18.1 Prototypes
  23.18.2 Construction
  23.18.3 Slots
 23.19 Finalizable
  23.19.1 Example
  23.19.2 Prototypes
  23.19.3 Construction
  23.19.4 Slots
 23.20 Float
  23.20.1 Prototypes
  23.20.2 Construction
  23.20.3 Slots
 23.21 Float.limits
  23.21.1 Slots
 23.22 FormatInfo
  23.22.1 Prototypes
  23.22.2 Construction
  23.22.3 Slots
 23.23 Formatter
  23.23.1 Prototypes
  23.23.2 Construction
  23.23.3 Slots
 23.24 Global
  23.24.1 Prototypes
  23.24.2 Slots
 23.25 Group
  23.25.1 Example
  23.25.2 Prototypes
  23.25.3 Construction
  23.25.4 Slots
 23.26 Hash
  23.26.1 Prototypes
  23.26.2 Construction
  23.26.3 Slots
 23.27 InputStream
  23.27.1 Prototypes
  23.27.2 Construction
  23.27.3 Slots
 23.28 IoService
  23.28.1 Example
  23.28.2 Prototypes
  23.28.3 Construction
  23.28.4 Slots
 23.29 Job
  23.29.1 Prototypes
  23.29.2 Construction
  23.29.3 Slots
 23.30 Kernel1
  23.30.1 Prototypes
  23.30.2 Construction
  23.30.3 Slots
 23.31 Lazy
  23.31.1 Examples
   23.31.1.1 Evaluating once
   23.31.1.2 Evaluating several times
  23.31.2 Caching
  23.31.3 Prototypes
  23.31.4 Construction
  23.31.5 Slots
 23.32 List
  23.32.1 Prototypes
  23.32.2 Examples
  23.32.3 Construction
  23.32.4 Slots
 23.33 Loadable
  23.33.1 Prototypes
  23.33.2 Example
  23.33.3 Construction
  23.33.4 Slots
 23.34 Lobby
  23.34.1 Prototypes
  23.34.2 Construction
  23.34.3 Examples
  23.34.4 Slots
 23.35 Location
  23.35.1 Prototypes
  23.35.2 Construction
  23.35.3 Slots
 23.36 Logger
  23.36.1 Examples
  23.36.2 Prototypes
  23.36.3 Construction
  23.36.4 Slots
 23.37 Math
  23.37.1 Prototypes
  23.37.2 Construction
  23.37.3 Slots
 23.38 Mutex
  23.38.1 Prototypes
  23.38.2 Construction
  23.38.3 Slots
 23.39 nil
  23.39.1 Prototypes
  23.39.2 Construction
  23.39.3 Slots
 23.40 Object
  23.40.1 Prototypes
  23.40.2 Construction
  23.40.3 Slots
 23.41 Orderable
 23.42 OutputStream
  23.42.1 Prototypes
  23.42.2 Construction
  23.42.3 Slots
 23.43 Pair
  23.43.1 Prototype
  23.43.2 Construction
  23.43.3 Slots
 23.44 Path
  23.44.1 Prototypes
  23.44.2 Construction
  23.44.3 Slots
 23.45 Pattern
  23.45.1 Prototypes
  23.45.2 Construction
  23.45.3 Slots
 23.46 Position
  23.46.1 Prototypes
  23.46.2 Construction
  23.46.3 Slots
 23.47 Primitive
  23.47.1 Prototypes
  23.47.2 Construction
  23.47.3 Slots
 23.48 Process
  23.48.1 Prototypes
  23.48.2 Example
  23.48.3 Construction
  23.48.4 Slots
 23.49 Profile
  23.49.1 Example
   23.49.1.1 Basic profiling
   23.49.1.2 Asynchronous profiling
  23.49.2 Prototypes
  23.49.3 Construction
  23.49.4 Slots
 23.50 Profile.Function
  23.50.1 Prototypes
  23.50.2 Construction
  23.50.3 Slots
 23.51 PseudoLazy
 23.52 PubSub
  23.52.1 Prototypes
  23.52.2 Construction
  23.52.3 Slots
 23.53 PubSub.Subscriber
  23.53.1 Prototypes
  23.53.2 Construction
  23.53.3 Slots
 23.54 RangeIterable
  23.54.1 Prototypes
  23.54.2 Slots
 23.55 Regexp
  23.55.1 Prototypes
  23.55.2 Construction
  23.55.3 Slots
 23.56 Semaphore
  23.56.1 Prototypes
  23.56.2 Construction
  23.56.3 Slots
 23.57 Server
  23.57.1 Prototypes
  23.57.2 Construction
  23.57.3 Slots
 23.58 Singleton
  23.58.1 Prototypes
  23.58.2 Construction
  23.58.3 Slots
 23.59 Socket
  23.59.1 Example
  23.59.2 Prototypes
  23.59.3 Construction
  23.59.4 Slots
 23.60 StackFrame
  23.60.1 Construction
  23.60.2 Slots
 23.61 Stream
  23.61.1 Prototypes
  23.61.2 Construction
  23.61.3 Slots
 23.62 String
  23.62.1 Prototypes
  23.62.2 Construction
  23.62.3 Slots
 23.63 System
  23.63.1 Prototypes
  23.63.2 Slots
 23.64 System.PackageInfo
  23.64.1 Prototypes
  23.64.2 Slots
 23.65 System.Platform
  23.65.1 Prototypes
  23.65.2 Slots
 23.66 Tag
  23.66.1 Examples
   23.66.1.1 Stop
   23.66.1.2 Block/unblock
   23.66.1.3 Freeze/unfreeze
   23.66.1.4 Scope tags
   23.66.1.5 Enter/leave events
   23.66.1.6 Begin/end
  23.66.2 Construction
  23.66.3 Slots
  23.66.4 Hierarchical tags
 23.67 Timeout
  23.67.1 Prototypes
  23.67.2 Construction
  23.67.3 Examples
  23.67.4 Slots
 23.68 Traceable
  23.68.1 Slots
 23.69 TrajectoryGenerator
  23.69.1 Prototypes
  23.69.2 Examples
   23.69.2.1 Accel
   23.69.2.2 Cos
   23.69.2.3 Sin
   23.69.2.4 Smooth
   23.69.2.5 Speed
   23.69.2.6 Time
   23.69.2.7 Trajectories and Tags
  23.69.3 Construction
  23.69.4 Slots
 23.70 Triplet
  23.70.1 Prototype
  23.70.2 Construction
  23.70.3 Slots
 23.71 Tuple
  23.71.1 Prototype
  23.71.2 Construction
  23.71.3 Slots
 23.72 UObject
  23.72.1 Prototypes
  23.72.2 Slots
 23.73 uobjects
  23.73.1 Prototypes
  23.73.2 Slots
 23.74 UValue
 23.75 UVar
  23.75.1 Construction
  23.75.2 Prototypes
  23.75.3 Slots
 23.76 void
  23.76.1 Prototypes
  23.76.2 Construction
  23.76.3 Slots
24 Communication with ROS
 24.1 Ros
  24.1.1 Construction
  24.1.2 Slots
 24.2 Ros.Topic
  24.2.1 Construction
  24.2.2 Slots
   24.2.2.1 Common
   24.2.2.2 Subscription
   24.2.2.3 Advertising
  24.2.3 Example
 24.3 Ros.Service
  24.3.1 Construction
  24.3.2 Slots
25 Gostai Standard Robotics API
 25.1 The Structure Tree
 25.2 Frame of Reference
 25.3 Component naming
 25.4 Localization
 25.5 Interface
  25.5.1 AudioIn
  25.5.2 AudioOut
  25.5.3 Battery
  25.5.4 BlobDetector
  25.5.5 Identity
  25.5.6 Led
   25.5.6.1 RGBLed
  25.5.7 Mobile
   25.5.7.1 Blocking API
   25.5.7.2 Speed-control API
   25.5.7.3 Safety
   25.5.7.4 State
  25.5.8 Motor
   25.5.8.1 LinearMotor
   25.5.8.2 LinearSpeedMotor
   25.5.8.3 RotationalMotor
   25.5.8.4 RotationalSpeedMotor
  25.5.9 Network
  25.5.10 Sensor
   25.5.10.1 AccelerationSensor
   25.5.10.2 DistanceSensor
   25.5.10.3 GyroSensor
   25.5.10.4 Laser
   25.5.10.5 TemperatureSensor
   25.5.10.6 TouchSensor
  25.5.11 SpeechRecognizer
  25.5.12 TextToSpeech
  25.5.13 Tracker
  25.5.14 VideoIn
 25.6 Standard Components
  25.6.1 Yaw/Pitch/Roll orientation
  25.6.2 Standard Component List
 25.7 Compact notation
 25.8 Support classes
  25.8.1 Interface
  25.8.2 Component
  25.8.3 Localizer
V  Urbi Platforms
26 Aldebaran Nao
 26.1 Introduction
 26.2 Starting up
 26.3 Accessing joints
  26.3.1 Advanced parameters
   26.3.1.1 Trajectory generator period
   26.3.1.2 Motor back-end method
   26.3.1.3 Motor command debugging
 26.4 Leds
 26.5 Camera
  26.5.1 Slots
 26.6 Whole body motion
 26.7 Other sensors
 26.8 Interfacing with NaoQi
  26.8.1 Accessing the NaoQi shared memory region
  26.8.2 Accessing standard NaoQi modules
  26.8.3 Binding new NaoQi modules in Urbi
  26.8.4 Writing NaoQi modules in Urbi
  26.8.5 More examples
27 Bioloid
 27.1 Introduction
 27.2 Installing Urbi for Bioloid
  27.2.1 Flashing the firmware
  27.2.2 Getting Urbi and Urbi for Bioloid
 27.3 First steps
  27.3.1 Starting up
  27.3.2 Motor features
  27.3.3 Sensor features
28 Mindstorms NXT
 28.1 Launching Urbi for Mindstorms NXT
 28.2 First steps with Urbi to control Mindstorms NXT
  28.2.1 Make basic movements
  28.2.2 Improving the movements
  28.2.3 Reading sensors
  28.2.4 Tagging commands
  28.2.5 Playing sounds
  28.2.6 Cyclic moves
  28.2.7 Parallelism
  28.2.8 Using functions
  28.2.9 Loading files
  28.2.10 Conclusion
 28.3 Default layout reference
  28.3.1 Motors
  28.3.2 Sensors
   28.3.2.1 Bumper
   28.3.2.2 Sonar
   28.3.2.3 Decibel
   28.3.2.4 Light
  28.3.3 Battery
  28.3.4 Beeper
  28.3.5 Command
 28.4 How to make its own layout
  28.4.1 Instantiating Motors
  28.4.2 Instantiating sensors
  28.4.3 Other devices
 28.5 Available UObject Devices
  28.5.1 Servo
  28.5.2 UltraSonicSensor
  28.5.3 SoundSensor
  28.5.4 LightSensor
  28.5.5 Switch
  28.5.6 Battery
  28.5.7 Beeper
  28.5.8 Command
  28.5.9 Instances
  28.5.10 Groups
29 Gostai Open Jazz
 29.1 Getting started
  29.1.1 Documentation and Support
   29.1.1.1 Jazz User Manual
   29.1.1.2 Getting Support
  29.1.2 Requirements
  29.1.3 Embedded Software
  29.1.4 Connecting Jazz to your Local Area Network
  29.1.5 Connecting to Jazz from your Computer
   29.1.5.1 Obtaining Jazz IP Address
   29.1.5.2 Gostai Suite
   29.1.5.3 Telnet Connection to Urbi on Jazz
   29.1.5.4 Ssh Access to Jazz Filesystem
  29.1.6 Jazz internal website
  29.1.7 Uploading and loading your code on Jazz
   29.1.7.1 The User Services web page
   29.1.7.2 Uploading Files on Jazz Filesystem using scp
  29.1.8 Updating Jazz Software
  29.1.9 Restarting Jazz Software
  29.1.10 Changing Software Profile
  29.1.11 Using the Examples
   29.1.11.1 urbiscript Examples
   29.1.11.2 UObjects examples
 29.2 urbiscript API
  29.2.1 Eye leds
   29.2.1.1 robot.body.head.eye
   29.2.1.2 Example
  29.2.2 Docking
  29.2.3 Head Motors
   29.2.3.1 robot.body.head
   29.2.3.2 Example
  29.2.4 Microphone
   29.2.4.1 Quickly Record the Audio Stream
   29.2.4.2 robot.body.head.micro
   29.2.4.3 Example
  29.2.5 Network
   29.2.5.1 robot.network
   29.2.5.2 Example
  29.2.6 Playing Sound
   29.2.6.1 Example
  29.2.7 Text to Speech
   29.2.7.1 Example
  29.2.8 Video Camera
   29.2.8.1 Visualize the Video Stream
   29.2.8.2 robot.camera
   29.2.8.3 Example
  29.2.9 Movement
   29.2.9.1 urbiscript interface
   29.2.9.2 Example
  29.2.10 Screen Display
   29.2.10.1 From urbiscript
   29.2.10.2 Command Line
  29.2.11 Sonars
   29.2.11.1 urbiscript Interface
   29.2.11.2 Example
  29.2.12 IRs
   29.2.12.1 urbiscript Interface
   29.2.12.2 Example
  29.2.13 Laser
   29.2.13.1 robot.body.laser
 29.3 urbiscript Library
  29.3.1 AlsaMicrophone
  29.3.2 AlsaSpeaker
  29.3.3 EchoCanceller
 29.4 urbiscript Interfaces
   29.4.0.1 AutomaticGainControl
   29.4.0.2 Denoiser
 29.5 Troubleshooting
  29.5.1 Get Jazz Version
  29.5.2 Access Jazz Logs
  29.5.3 Debug your Urbi Code
   29.5.3.1 Monitor urbiscript Job Execution
   29.5.3.2 Monitor UObjects Execution Time
  29.5.4 Enable Core Dump
  29.5.5 Monitor Jazz Processor and Memory Load
  29.5.6 Monitor Jazz Hard-Drive Space
  29.5.7 I/O Issues when Powering Robot Off
 29.6 ROS support
  29.6.1 About ROS
  29.6.2 ROS support in Jazz
  29.6.3 Enabling and configuring ROS service
  29.6.4 Predefined topics
  29.6.5 Using the navigation stack with ROS
   29.6.5.1 Creating a map of your environment
   29.6.5.2 Autonomous navigation
   29.6.5.3 Troubleshooting
30 Pioneer 3-DX
 30.1 Getting started
  30.1.1 Prerequisites
  30.1.2 Installation
  30.1.3 Running
 30.2 How to use Pioneer 3-DX robot
  30.2.1 P3dx
  30.2.2 P3dx.body
  30.2.3 P3dx.body.odometry
  30.2.4 P3dx.body.sonar
  30.2.5 P3dx.body.laser
  30.2.6 P3dx.body.camera
  30.2.7 P3dx.body.x
  30.2.8 P3dx.body.yaw
  30.2.9 P3dx.planner
  30.2.10 P3dx.body.battery
 30.3 Mobility modes
 30.4 About units
31 Segway RMP
 31.1 RMP
  31.1.1 Instantiation
  31.1.2 Slots
 31.2 GSRAPI compliance
32 Spykee
 32.1 Installing Urbi on the Spykee
 32.2 Device list
 32.3 Dynamically loaded modules
  32.3.1 Clapper
33 Webots
 33.1 Setup
  33.1.1 Installation
   33.1.1.1 Linux
   33.1.1.2 Mac OS X
   33.1.1.3 Windows
  33.1.2 License
   33.1.2.1 Evaluation mode
   33.1.2.2 Setting up a license
 33.2 Using Urbi as a controller in your Webots worlds
  33.2.1 Using the default urbi-2.0 controller
  33.2.2 Defining custom Urbi controllers
 33.3 Binding your own robots with Urbi for Webots
 33.4 Built-in robots and worlds
 33.5 Webots UObjects
  33.5.1 Robot devices UObjects
   33.5.1.1 Accelerometer
   33.5.1.2 Camera
   33.5.1.3 Differential Wheels
   33.5.1.4 Distance Sensor
   33.5.1.5 Led
   33.5.1.6 Servo
   33.5.1.7 Touch Sensor
  33.5.2 Supervisor API UObjects
   33.5.2.1 Label
   33.5.2.2 Manipulate Node
   33.5.2.3 Simulation Controller
VI  Tables and Indexes
34 Notations
 34.1 Words
 34.2 Frames
  34.2.1 C++ Code
  34.2.2 Grammar Excerpts
  34.2.3 Java Code
  34.2.4 Shell Sessions
  34.2.5 urbiscript Sessions
  34.2.6 urbiscript Assertions
35 Release Notes
 35.1 Urbi SDK 2.7.5
  35.1.1 Fixes
  35.1.2 Changes
  35.1.3 New Feature
  35.1.4 Documentation
 35.2 Urbi SDK 2.7.4
  35.2.1 Fixes
  35.2.2 Changes
  35.2.3 Documentation
 35.3 Urbi SDK 2.7.3
  35.3.1 Fixes
  35.3.2 Changes
  35.3.3 Documentation
 35.4 Urbi SDK 2.7.2
  35.4.1 Fixes
 35.5 Urbi SDK 2.7.1
  35.5.1 Fixes
  35.5.2 Changes
  35.5.3 Documentation
 35.6 Urbi SDK 2.7
  35.6.1 Changes
  35.6.2 New Features
  35.6.3 Documentation
 35.7 Urbi SDK 2.6
  35.7.1 Fixes
  35.7.2 Optimizations
  35.7.3 New Features
  35.7.4 Documentation
 35.8 Urbi SDK 2.5
  35.8.1 Fixes
  35.8.2 New Features
  35.8.3 Changes
  35.8.4 Documentation
 35.9 Urbi SDK 2.4
  35.9.1 Fixes
  35.9.2 New Features
  35.9.3 Documentation
 35.10 Urbi SDK 2.3
  35.10.1 Fixes
  35.10.2 New Features
 35.11 Urbi SDK 2.2
  35.11.1 Fixes
  35.11.2 New Features
  35.11.3 Documentation
 35.12 Urbi SDK 2.1
  35.12.1 Fixes
  35.12.2 New Features
  35.12.3 Optimization
  35.12.4 Documentation
 35.13 Urbi SDK 2.0.3
  35.13.1 New Features
  35.13.2 Fixes
  35.13.3 Documentation
 35.14 Urbi SDK 2.0.2
  35.14.1 urbiscript
  35.14.2 Fixes
  35.14.3 Documentation
 35.15 Urbi SDK 2.0.1
  35.15.1 urbiscript
  35.15.2 Documentation
  35.15.3 Fixes
 35.16 Urbi SDK 2.0
  35.16.1 urbiscript
   35.16.1.1 Changes
   35.16.1.2 New features
  35.16.2 UObjects
  35.16.3 Documentation
 35.17 Urbi SDK 2.0 RC 4
  35.17.1 urbiscript
   35.17.1.1 Changes
   35.17.1.2 New objects
   35.17.1.3 New features
  35.17.2 UObjects
 35.18 Urbi SDK 2.0 RC 3
  35.18.1 urbiscript
   35.18.1.1 Fixes
   35.18.1.2 Changes
  35.18.2 Documentation
 35.19 Urbi SDK 2.0 RC 2
  35.19.1 Optimization
  35.19.2 urbiscript
   35.19.2.1 New constructs
   35.19.2.2 New objects
   35.19.2.3 New features
   35.19.2.4 Fixes
   35.19.2.5 Deprecations
   35.19.2.6 Changes
  35.19.3 UObjects
  35.19.4 Documentation
  35.19.5 Various
 35.20 Urbi SDK 2.0 RC 1
  35.20.1 Auxiliary programs
  35.20.2 urbiscript
   35.20.2.1 Changes
   35.20.2.2 Fixes
  35.20.3 URBI Remote SDK
  35.20.4 Documentation
 35.21 Urbi SDK 2.0 beta 4
  35.21.1 Documentation
  35.21.2 urbiscript
   35.21.2.1 Bug fixes
   35.21.2.2 Changes
  35.21.3 Programs
   35.21.3.1 Environment variables
   35.21.3.2 Scripting
   35.21.3.3 urbi-console
   35.21.3.4 Auxiliary programs
 35.22 Urbi SDK 2.0 beta 3
  35.22.1 Documentation
  35.22.2 urbiscript
   35.22.2.1 Fixes
   35.22.2.2 Changes
  35.22.3 UObjects
  35.22.4 Auxiliary programs
 35.23 Urbi SDK 2.0 beta 2
  35.23.1 urbiscript
  35.23.2 Standard library
  35.23.3 UObjects
  35.23.4 Run-time
  35.23.5 Bug fixes
  35.23.6 Auxiliary programs
36 Licenses
 36.1 Boost Software License 1.0
 36.2 BSD License
 36.3 Expat License
 36.4 gnu.bytecode
 36.5 ICU License
 36.6 Independent JPEG Group’s Software License
 36.7 Libcoroutine License
 36.8 OpenSSL License
 36.9 ROS
 36.10 Urbi Open Source Contributor Agreement
37 Bibliography
38 Glossary
39 List of Tables
40 List of Figures

Chapter 2
Getting Started

urbiscript comes with a set of tools, two of which being of particular importance:

urbi
launches an Urbi server. There are several means to interact with it, which we will see later.
urbi-launch
runs Urbi components, the UObjects, and connects them to an Urbi server.

Please, first make sure that these tools are properly installed. If you encounter problems, please see the frequently asked questions (Chapter 17), and the detailed installation instructions (Chapter 16).

 
# Make sure urbi is properly installed. 
$ urbi --version 
Urbi version 2.7.4 rev. 268868e 
Copyright (C) 2004-2012 Gostai S.A.S.. 
 
Libport version urbi-sdk-2.7.4 rev. f870ce6 
Copyright (C) 2005-2012 Gostai S.A.S..  

There are several means to interact with a server spawned by urbi, see Section 21.3 for details. First of all, you may use the options ‘-e’/‘--expression code ’ and ‘-f’/‘--file file ’ to send some code or the contents of some file to the newly run server. The option ‘q’/‘--quiet’ discards the banner.

You may combine any number of these options, but beware that being event-driven, the server does not “know” when a program ends. Therefore, batch programs should end by calling shutdown. Using a Unix shell:

 
# A classical program. 
$ urbi -q -e ’echo("Hello, World!");’ -e ’shutdown;’ 
[00000004] *** Hello, World!  
Listing 2.1: A batch session under Unix.

If you are running Windows, then, since the quotation rules differ, run:

 
# A classical program. 
$ urbi -q -e "echo(""Hello, World!"");" -e "shutdown;" 
[00000004] *** Hello, World!  
Listing 2.2: A batch session under Windows.

To run an interactive session, use option ‘-i’/‘--interactive’. Like most interactive interpreters, Urbi will evaluate the given commands and print out the results.

 
$ urbi -i 
[00000825] *** ******************************************************** 
[00000825] *** Urbi version 2.7.4 rev. 268868e 
[00000825] *** Copyright (C) 2004-2012 Gostai S.A.S. 
[00000825] *** 
[00000825] *** This program comes with ABSOLUTELY NO WARRANTY.  It can 
[00000825] *** be used under certain conditions.  Type ‘license;’, 
[00000825] *** ‘authors;’, or ‘copyright;’ for more information. 
[00000825] *** 
[00000825] *** Check our community site: http://www.urbiforge.org. 
[00000825] *** ******************************************************** 
1+2; 
[00001200] 3 
shutdown;  
Listing 2.3: An interactive session under Unix.

The output from the server is prefixed by a number surrounded by square brackets: this is the date (in milliseconds since the server was launched) at which that line was sent by the server. This is useful at occasions, since Urbi is meant to run many parallel commands. But since these timestamps are irrelevant in most examples, they will often be filled with zeroes through this documentation.

Under Unix, the program rlwrap provides additional services (history of commands, advanced command line edition etc.); run ‘rlwrap urbi -i’.

In either case the server can also be made available for network-based interactions using option ‘--port port ’. Note that while shutdown asks the server to quit, quit only quits one interactive session. In the following example (under Unix) the server is still available for other, possibly concurrent, sessions.

 
$ urbi --port 54000 & 
[1] 77024 
$ telnet localhost 54000 
Trying 127.0.0.1... 
Connected to localhost. 
Escape character is ’^]’
[00004816] *** ******************************************************** 
[00004816] *** Urbi version 2.7.4 rev. 268868e 
[00004816] *** Copyright (C) 2004-2012 Gostai S.A.S. 
[00004816] *** 
[00004816] *** This program comes with ABSOLUTELY NO WARRANTY.  It can 
[00004816] *** be used under certain conditions.  Type ‘license;’, 
[00004816] *** ‘authors;’, or ‘copyright;’ for more information. 
[00004816] *** 
[00004816] *** Check our community site: http://www.urbiforge.org. 
[00004816] *** ******************************************************** 
12345679*8; 
[00018032] 98765432 
quit; 
Connection closed by foreign host.  
Listing 2.4: An interactive session under Unix.

Under Windows, instead of using telnet, you may use Gostai Console (part of the package), which provides a Graphical User Interface to a network-connection to an Urbi server. To launch the server, run:

 
C:\...> start urbi --port 54000  
Listing 2.5: Starting an interactive session under Windows.

and to launch the client, click on Gostai Console which is installed by the installer.

Then, the interaction proceeds in the Gostai Console windows. Specify the host name and port to use (‘127.0.0.1:54000’) in the text field in the top of the window and click on the right to start the connection.

PIC

The program urbi-send (see Section 21.8) provides a nice interface to send batches of instructions (and/or files) to a running server.

 
$ urbi-send -P 54000 -e "1+2*3;" -Q 
[00018032] 7 
# Have the server shutdown; 
$ urbi-send -P 54000 -e "shutdown;"  

You can now send commands to your Urbi server. If at any point you get lost, or want a fresh start, you can simply close and reopen your connection to the server to get a clean environment. In some cases, particularly if you made global changes in the environment, it is simpler to start anew: shut your current server down using the command shutdown, and spawn a new one. In interactive mode you can also use the shortcut sequence Ctrl-D, like in many other interpreters.

In case of a foreground task preventing you to execute other commands, you can use Ctrl-C to kill the foreground task, clear queued commands and restore interactive mode.

You are now ready to proceed to the urbiscript tutorial: see Part II.

Enjoy!

Part I
Urbi and UObjects User Manual

About This Part

This part covers the Urbi architecture: its core components (client/server architecture), how its middleware works, how to include extensions as UObjects (C++ components) and so forth.

No knowledge of the urbiscript language is needed. As a matter of fact, Urbi can be used as a standalone middleware architecture to orchestrate the execution of existing components.

Yet urbiscript is a feature that “comes for free”: it is easy using it to experiment, prototype, and even program fully-featured applications that orchestrate native components. The interested reader should read either the urbiscript user manual (Part II), or the reference manual (Chapter 22).

  Chapter 3 Quick Start
 
This chapter, self-contained, shows the potential of Urbi used as a middleware.
  Chapter 4 The UObject API
 
This section shows the various steps of writing an Urbi C++ component using the UObject API.
  Chapter 5 The UObject Java API
 
UObjects can also be written in Java. This section demonstrates it all.
  Chapter 6 Use Cases
 
Interfacing a servomotor device as an example on how to use the UObject architecture as a middleware.

Chapter 3
Quick Start

This chapter presents Urbi SDK with a specific focus on its middleware features. It is self-contained in order to help readers quickly grasp the potential of Urbi used as a middleware. References to other sections of this document are liberally provided to point the reader to the more complete documentation; they should be ignored during the first reading.

3.1 UObject Basics

As a simple running example, consider a (very) basic factory. Raw material delivered to the factory is pushed into some assembly machines, which takes some time.

3.1.1 The Objects to Bind into Urbi

As a firth component of this factory, the core machine of the factory is implemented as follows. This class is pure regular C++, it uses no Urbi feature at all.

The header ‘machine.hh’, which declares Machine, is traditional. The documentation uses the Doxygen syntax.

 
#ifndef MACHINE_MACHINE_HH 
# define MACHINE_MACHINE_HH 
 
# include <urbi/uobject.hh> 
 
class Machine 
{ 
public: 
  /// Construction. 
  /// \param duration  how long the assembly process takes. 
  ///                  In seconds. 
  Machine(float duration); 
 
  /// Lists of strings. 
  typedef std::list<std::string> strings; 
 
  /// Assemble the raw components into a product. 
  std::string operator()(const strings& components) const; 
 
  /// The duration of the assembly process, in seconds. 
  /// Must be positive. 
  float duration; 
}; 
 
#endif // ! MACHINE_MACHINE_HH

The implementation file, ‘machine.cc’, is equally straightforward.

 
// A wrapper around Boost.Foreach. 
#include <libport/foreach.hh> 
 
#include "machine.hh" 
 
Machine::Machine(float d) 
  : duration(d) 
{ 
  assert(0 <= d); 
} 
 
std::string 
Machine::operator()(const strings& components) const 
{ 
  // Waiting for duration seconds. 
  useconds_t one_second = 1000 * 1000; 
  usleep(useconds_t(duration * one_second)); 
 
  // Iterate over the list of strings (using Boost.Foreach), and 
  // concatenate them in res. 
  std::string res; 
  foreach (const std::string& s, components) 
    res += s; 
  return res; 
}

3.1.2 Wrapping into an UObject

By binding a UObject, we mean using the UObject API to declare objects to the Urbi world. These objects have member variables (also known as attributes) and/or member functions (also known as methods) all of them or some of them being declared to Urbi.

One could modify the Machine class to make it a UObject, yet we recommend wrapping pure C++ classes into a different, wrapping, UObject. It is strongly suggested to aggregate the native C++ objects in the UObject — rather than trying to derive from it. By convention, we prepend a “U” to the name of the base class, hence the UMachine class. This class provides a simplified interface, basically restricted to what will be exposed to Urbi. It must derive from urbi::UObject.

 
#ifndef MACHINE_UMACHINE_HH 
# define MACHINE_UMACHINE_HH 
 
// Include the UObject declarations. 
# include <urbi/uobject.hh> 
 
// We wrap factories. 
# include "machine.hh" 
 
/// A UObject wrapping a machine object. 
class UMachine 
  : public urbi::UObject 
{ 
public: 
  /// C++ contructor. 
  /// \param name  name given to the instance. 
  UMachine(const std::string& name); 
 
  /// Urbi constructor. 
  /// \param d  the duration of the assembly process. 
  ///           Must be positive. 
  /// \return 0 on success. 
  int init(ufloat d); 
 
  /// Wrapper around Machine::operator(). 
  std::string assemble(std::list<std::string> components); 
 
  /// Function notified when the duration is changed. 
  /// \param v   the UVar being modified (i.e., UMachine::duration). 
  /// \return 0  on success. 
  int duration_set(urbi::UVar& v); 
 
private: 
  /// The duration of the assembly process. 
  urbi::UVar duration; 
 
  /// The actual machine, wrapped in this UObject. 
  Machine* machine; 
}; 
#endif // ! MACHINE_UMACHINE_HH

The implementation of UMachine is simple. It uses some of the primitives used in the binding process (Section 4.2):

Urbi relies on the prototype model for object-oriented programming, which is somewhat different from the traditional C++ class-based model (Chapter 8). This is reflected by the presence of two different constructors:

The following listing is abundantly commented, and is easy to grasp.

 
#include "umachine.hh" 
 
// Register the UMachine UObject in the Urbi world. 
UStart(UMachine); 
 
// Bouncing the name to the UObject constructor is mandatory. 
UMachine::UMachine(const std::string& name) 
  : urbi::UObject(name) 
  , machine(0) 
{ 
  // Register the Urbi constructor.  This is the only mandatory 
  // part of the C++ constructor. 
  UBindFunction(UMachine, init); 
} 
 
int 
UMachine::init(ufloat d) 
{ 
  // Failure on invalid arguments. 
  if (d < 0) 
    return 1; 
 
  // Bind the functions, i.e., declare them to the Urbi world. 
  UBindFunction(UMachine, assemble); 
  UBindThreadedFunctionRename 
    (UMachine, assemble, "threadedAssemble", urbi::LOCK_FUNCTION); 
  // Bind the UVars before using them. 
  UBindVar(UMachine, duration); 
 
  // Set the duration. 
  duration = d; 
  // Build the machine. 
  machine = new Machine(d); 
 
  // Request that duration_set be invoked each time duration is 
  // changed.  Declared after the above "duration = d" since we dont 
  // want it to be triggered for this first assignment. 
  UNotifyChange(duration, &UMachine::duration_set); 
 
  // Success. 
  return 0; 
} 
 
int 
UMachine::duration_set(urbi::UVar& v) 
{ 
  assert(machine); 
  ufloat d = static_cast<ufloat>(v); 
  if (0 <= d) 
  { 
    // Valid value. 
    machine->duration = d; 
    return 0; 
  } 
  else 
    // Report failure. 
    return 1; 
} 
 
 
std::string 
UMachine::assemble(std::list<std::string> components) 
{ 
  assert(machine); 
 
  // Bounce to Machine::operator(). 
  return (*machine)(components); 
}

3.1.3 Running Components

As a first benefit from using the Urbi environment, this source code is already runnable! No main function is needed, the Urbi system provides one.

3.1.3.1 Compiling

Of course, beforehand, we need to compile this UObject into some loadable module. The Urbi modules are shared objects, i.e., libraries that can be loaded on demand (and unloaded) during the execution of the program. Their typical file names depend on the architecture: ‘machine.so’ on most Unix platforms (including Mac OS X), and ‘machine.dll’ on Windows. To abstract away from these differences, we will simply use the base name, ‘machine’ with the Urbi tool chain.

There are several options to compile our machine as a UObject. If you are using Microsoft Visual Studio, the Urbi SDK installer created a “UObject” project template accessible through the “New project” wizard. Otherwise, you can use directly your regular compiler tool chain. You may also use umake-shared from the ‘umake-*’ family of programs (Section 21.10.2):

 
$ ls machine.uob 
machine.cc  machine.hh  umachine.cc  umachine.hh 
$ umake-shared machine.uob -o machine 
# ... Lots of compilation log messages ... 
$ ls 
_ubuild-machine.so  machine.la  machine.so  machine.uob  

The various files are:

machine.uob
Merely by convention, the sources of our UObject are in a ‘*.uob’ directory.
machine.so
A shared dlopen-module. This is the “true” product of the umake-shared invocation. Its default name can be quite complex (‘uobject-i386-apple-darwin9.7.0.so’ on my machine), as it will encode information about the architecture of your machine; if you don’t need such accuracy, use the option ‘--output’/‘-o’ to specify the output file name.

umake-shared traversed ‘machine.uob’ to gather and process relevant files (source files, headers, libraries and object files) in order to produce this output file.

_ubuild-machine.so
this is a temporary directory in which the compilation takes place. It can be safely removed by hand, or using umake-deepclean (Section 21.10.2).
machine.la
a GNU Libtool file that contains information such as dependencies on other libraries. While this file should be useless most of the time, we recommend against removing it: it may help understand some problems.

3.1.3.2 Running UObjects

There are several means to toy with this simple UObject. You can use urbi-launch (Section 21.5) to plug the UMachine in an Urbi server and enter an interactive session.

 
# Launch an Urbi server with UMachine plugged in. 
$ urbi-launch --start machine -- --interactive 
[00000000] *** ******************************************************** 
[00000000] *** Urbi SDK version 2.7 rev. a6a1ec5 
[00000000] *** Copyright (C) 2004-2011 Gostai S.A.S. 
[00000000] *** 
[00000000] *** This program comes with ABSOLUTELY NO WARRANTY.  It can 
[00000000] *** be used under certain conditions.  Type ‘license;’, 
[00000000] *** ‘authors;’, or ‘copyright;’ for more information. 
[00000000] *** 
[00000000] *** Check our community site: http://www.urbiforge.org. 
[00000000] *** ******************************************************** 
var f = UMachine.new(1s); 
[00020853] UMachine_0x1899c90 
f.assemble(["Hello, ""World!"]); 
[00038705] "Hello, World!" 
shutdown;  

You may also launch the machine UObject in the background, as a network component:

 
$ urbi-launch --start machine --host 0.0.0.0 --port 54000 &  

and interact with it using your favorite client (telnet, netcat, socat, …), or using the urbi-send tool (Section 21.8).

 
$ urbi-send --port 54000                       \ 
            -e ’UMachine.assemble([12, 34]);’  \ 
            --quit 
[00126148] "1234" 
[00000000:client_error] End of file 
$ urbi-send --port 54000                     \ 
            -e ’var f = UMachine.new(1s)|’   \ 
            -e ’f.assemble(["ab", "cd"]);’   \ 
            --quit 
[00146159] "abcd" 
[00000000:client_error] End of file  

3.2 Using urbiscript

urbiscript is a programming language primarily designed for robotics. Its syntax is inspired by that of C++: if you know C, C++, Java or C#, writing urbiscript programs is easy. It’s a dynamic object-oriented (Chapter 11) scripting language, which makes it well suited for high-level application. It supports and emphasizes parallel (Chapter 13) and event-based programming (Chapter 14), which are very popular paradigms in robotics, by providing core primitives and language constructs.

Thanks to its client/server approach, one can easily interact with a robot, to monitor it, or to experiment live changes in the urbiscript programs.

Courtesy of the UObject architecture, urbiscript is fully integrated with C++. As already seen in the above examples (Section 3.1.3), you can bind C++ classes in urbiscript seamlessly. urbiscript is also integrated with many other languages such as Java (Chapter 5), MatLab or Python. The UObject framework also naturally provides urbiscript with support for distributed architectures: objects can run in different processes, possibly on remote computers.

3.2.1 The urbiscript Scripting Language

The following example shows how one can easily interface UObjects into the urbiscript language. The following simple class (actually, a genuine object, in urbiscript “classes are objects”, see Chapter 11) aggregates two assembly machines, a fast one, and a slow one. This class demonstrates usual object-oriented, sequential, features.

 
class TwoMachineFactory 

  // A shorthand common to all the Two Machine factories. 
  var UMachine = uobjects.UMachine; 
 
  // Default machines. 
  var fastMachine = UMachine.new(10ms); 
  var slowMachine = UMachine.new(100ms); 
 
  // The urbiscript constructor. 
  // Build two machines, a fast one, and a slow one. 
  function init(fast = 10ms, slow = 100ms) 
  { 
    // Make sure fast <= slow. 
    if (slow < fast) 
      [fast, slow] = [slow, fast]; 
    // Two machines for each instance of TwoMachineFactory. 
    fastMachine = UMachine.new(fast); 
    slowMachine = UMachine.new(slow); 
  }; 
 
  // Wrappers to make invocation of the machine simpler. 
  function fast(input) { fastMachine.assemble(input) }; 
  function slow(input) { slowMachine.assemble(input) }; 
 
  // Use the slow machine for large jobs. 
  function assemble(input) 
  { 
    var res| 
    var machine| 
    if (5 < input.size) 
      { machine = "slow" | res = slow(input); } 
    else 
      { machine = "fast" | res = fast(input); } | 
    echo ("Used the %s machine (%s => %s)" % [machine, input, res]) | 
    res 
  }; 
}; 
[00000001] TwoMachineFactory  

Using this class is straightforward.

 
var f = TwoMachineFactory.new|; 
f.assemble([1, 2, 3, 4, 5, 6]); 
[00000002] *** Used the slow machine ([1, 2, 3, 4, 5, 6] => 123456) 
[00000003] "123456" 
f.assemble([1]); 
[00000004] *** Used the fast machine ([1] => 1) 
[00000005] "1"  

The genuine power of urbiscript is when concurrency comes into play.

3.2.2 Concurrency

Why should we wait for the slow job to finish if we have a fast machine available? To do so, we must stop requesting a sequential composition between both calls. We did that by using the sequential operator, ‘;’. In urbiscript, there exists its concurrent counter-part: ‘,’. Indeed, running ab means “launch the program a and then launch the program b”. The urbiscript Manual contains a whole section devoted to explaining these operators (Chapter 13).

3.2.2.1 First Attempt

Let’s try it:

 
f.assemble([1, 2, 3, 4, 5, 6]), 
f.assemble([1]), 
[00000002] *** Used the slow machine ([1, 2, 3, 4, 5, 6] => 123456) 
[00000004] *** Used the fast machine ([1] => 1)  

This is a complete failure.

Why?

Since Urbi cannot expect that your code is thread-safe, by default all calls to UObject features are synchronous, or blocking: the whole Urbi system is suspended until the function returns. There is a single thread of execution for Urbi, and when calling a function from a (plugged) UObject, that thread of execution is devoted to evaluated the code.

See for instance below that, in even though f.assemble is slow and launched in background, the almost instantaneous display of ping is not performed immediately.

 
echo(f.slow([1, 2, 3, 4, 5, 6])), 
echo("ping"); 
[00000002] *** 123456 
[00000002] *** ping  

There are several means to address this unintended behavior. If the base library provides a threaded API (in our example, the Machine class, not the UMachine UObject wrapper), then you could use it. Yet we don’t recommend it, as it takes away from Urbi the possibility to really control concurrency issues (for instance it cannot turn non-blocking functions into blocking functions).

A better option is to ask Urbi to turn blocking function calls into non-blocking ones.

3.2.2.2 Second Attempt: Threaded Functions

If you read carefully the body of the UMachine::init function, you will find the following piece of code:

 
UBindFunction(UMachine, assemble); 
UBindThreadedFunctionRename 
  (UMachine, assemble, "threadedAssemble", urbi::LOCK_FUNCTION);  

Both calls bind the function UMachine::assemble, but the second one will run the call in a separate thread. Since multiple calls to a single function (or different functions of a single object etc.) are likely to fail, a locking model must be provided. Here, urbi::LOCK_FUNCTION means that concurrent calls to UMachine::assemble must be serialized: one at a time.

To use this threaded version of assemble, we can simply patch our TwoMachineFactory class:

 
do (TwoMachineFactory) 

  fast = function (input) { fastMachine.threadedAssemble(input) }; 
  slow = function (input) { slowMachine.threadedAssemble(input) }; 
}|;  

Let’s try again where we failed previously (Section 3.2.2.1):

 
f.assemble([1, 2, 3, 4, 5, 6]), 
f.assemble([1]), 
[00000004] *** Used the fast machine ([1] => 1) 
[00000002] *** Used the slow machine ([1, 2, 3, 4, 5, 6] => 123456) 
sleep(200ms);  

Victory! The fast machine answered first.

You may have noticed that the result is no longer reported. Indeed, the urbiscript interactive shell only displays the result of synchronous expressions (i.e., those ending with a ‘;’): asynchronous answers are confusing (see the inversion here).

Channels are useful to “send” asynchronous answers.

 
var c1 = Channel.new("c1")|; 
var c2 = Channel.new("c2")|; 
c1 << f.assemble([10, 20, 30, 40, 50, 60]), 
c2 << f.assemble([100]), 
sleep(200ms); 
[00000535] *** Used the fast machine ([100] => 100) 
[00000535:c2] "100" 
[00000625] *** Used the slow machine ([10, 20, 30, 40, 50, 60] => 102030405060) 
[00000625:c1] "102030405060"  

3.3 Conclusion

This section gave only a quick glance to all the power that Urbi provides to support concurrency. Actually, it makes plenty of sense to embed an Urbi engine in a native C++ program, and to delegate the concurrency issues to it. Thanks to its middleware and client/server architecture, it is then possible to connect it to remote components of different kinds, such as using ROS for instance.

Then, a host of features are at hand, ready to be used when you need them: event-driven programming, automatic monitoring of expressions, interactive sessions, …and, last but not least, the urbiscript programming language.

Chapter 4
The UObject API

The UObject API can be used to add new objects written in C++ to the urbiscript language, and to interact from C++ with the objects that are already defined. We cover the use cases of controlling a physical device (servomotor, speaker, camera…), and interfacing higher-lever components (voice recognition, object detection…) with Urbi.

The C++ API defines the UObject class. To each instance of a C++ class deriving from UObject will correspond an urbiscript object sharing some of its methods and attributes. The API provides methods to declare which elements of your object are to be shared. To share a variable with Urbi, you have to give it the type UVar. This type is a container that provides conversion and assignment operators for all types known to Urbi: double, std::string and char*, and the binary-holding structures UBinary, USound and UImage. This type can also read from and write to the liburbi UValue class. The API provides methods to set up callbacks functions that will be notified when a variable is modified or read from Urbi code. Instance methods of any prototype can be rendered accessible from urbiscript, providing all the parameters types and the return type can be converted to/from UValue.

4.1 Compiling UObjects

UObjects can be compiled easily directly with any regular compiler. Nevertheless, Urbi SDK provides two tools to compile UObject seamlessly.

In the following sections, we will try to compile a shared library named ‘factory.so’ (or ‘factory.dll’ on Windows platforms) from a set of four files (‘factory.hh’, ‘factory.cc’, ‘ufactory.hh’, ‘ufactory.cc’). These files are stored in a ‘factory.uob’ directory; its name bares no importance, yet the ‘*.uob’ extension makes clear that it is a UObject.

In what follows, urbi-root denotes the top-level directory of your Urbi SDK package, see Section 16.2.

4.1.1 Compiling by hand

On Unix platforms, compiling by hand into a shared library is straightforward:

 
$ g++ -I urbi-root/include \ 
      -fPIC -shared \ 
      factory.uob/*cc -o factory.so 
$ file factory.so 
factory.so: ELF 32-bit LSB shared object, Intel 80386, \ 
  version 1 (SYSV), dynamically linked, not stripped  

On Mac OS X the flags ‘-Wl,-undefined,dynamic_lookup’ are needed:

 
$ g++ -I urbi-root/include \ 
      -shared -Wl,-undefined,dynamic_lookup \ 
      factory.uob/*.cc -o factory.so 
$ file factory.so 
factory.so: Mach-O 64-bit dynamically linked shared library x86_64  

4.1.2 The umake-* family of tools

umake can be used to compile UObjects. See Section 21.10 for its documentation.

You can give it a list of files to compile:

 
$ umake -q --shared-library factory.uob/*.cc -o factory.so 
umake: running to build library.  

or directories in which C++ sources are looked for:

 
$ umake -q --shared-library factory.uob -o factory.so 
umake: running to build library.  

or finally, if you give no argument at all, the sources in the current directory:

 
cd factory.uob 
$ umake -q --shared-library -o factory.so 
umake: running to build library.  

4.1.3 Using the Visual C++ Wizard

If you installed Urbi SDK using its installer, and if you had Visual C++ installed, then the UObject wizard was installed. Use it to create your UObject code:

PIC

Then, compile your UObject.

PIC

And run it.

PIC

4.2 Creating a class, binding variables and functions

Let’s illustrate those concepts by defining a simple object: adder. This object has one variable v, and a method add that returns the sum of this variable and its argument.

To summarize:

4.3 Creating new instances

When you start an Urbi server, an object of each class registered with UStart is created with the same name as the class. New instances can be created from Urbi using the new method. For each instance created in Urbi, a corresponding instance of the C++ object is created. You can get the arguments passed to the constructor by defining and binding a method named init with the appropriate number of arguments.

4.4 Binding functions

4.4.1 Simple binding

You can register any member function of your UObject using the macro

UBindFunction(class-namefunction-name).

Once done, the function can be called from urbiscript.

The following types for arguments and return value are supported:

The procedure to register new types to this system is explained in Section 4.18.

4.4.2 Multiple bindings

If you have multiple functions to bind, you can use the UBindFunctions macro to bind multiple functions at once:

UBindFunctions(class-namefunction1function2...).

4.4.3 Asynchronous binding

Functions bound using UBindFunction are called synchronously, and thus block everything until they return.

If you wish to bind a function that requires a non-negligible amount of time to execute, you can have it execute in a separate thread by calling

UBindThreadedFunction(class-namefunction-namelock-mode).

The function code will be executed in a separate thread without breaking the urbiscript execution semantics.

The lock-mode argument can be used to prevent parallel execution of multiple bound functions if your code is not thread-safe. It can be any of the following values.

Other queue sizes can be used by passing LockSpec(LOCK_FUNCTION, my-queue-size) as lock-mode.

There is a restriction to the locking mechanism: you cannot mix multiple locking modes. For instance a function bound with LOCK_FUNCTION mode will not prevent another function bound with LOCK_INSTANCE from executing in parallel.

You can perform your own locking using semaphores if your code needs a more complex locking model.

You can limit the maximum number of threads that can run in parallel by using the setThreadLimit function.

4.5 Notification of a variable change or access

You can register a function that will be called each time a variable is modified by calling UNotifyChange(varfunc).

The function can take 0 or 1 argument. If the argument is of type UVar&, then the function will receive the UVar that was passed to UNotifyChange. If it is of any other type, then the new value in the UVar will be converted to this type and passed to the function.

In plugin mode, there is a similar mechanism to create a getter function that will be called each time an UVar is accessed: the UNotifyAccess function. It has the same signature as UNotifyChange, and calls the given function each time someone tries to access the UVar. The function can update the value in the UVar before the access takes place. Usage of UNotifyAccess should be reserved to infrequently used UVar that take a long time to update, as it disrupts the data flow between UObject.

You can remove all notifies associated to any given UVar by calling its unnotify function.

4.5.1 Threaded notification

In a manner similar to UBindThreadedFunction, you can request your callback function to be called in a separate thread by using UNotifyThreadedChange(varfunclock-mode).

The lock-mode argument has the same semantic as for bound functions.

There is one restriction: the callback function must not take a UVar& as argument. This restriction is here to ensure that each invocation of your callback will receive the correct value that the source UVar had at call time.

4.6 Data-flow based programming: exchanging UVars

The UNotifyChange and UNotifyAccess features can be used to link multiple UObjects together, and perform data-flow based programming: the UNotifyChange can be called to monitor UVars from other UObjects. Those UVars can be transmitted through bound function calls.

One possible pattern is to have each data-processing UObject take its input from monitored UVars, given in its constructor, and output the result of its processing in other UVars. Consider the following example of an object-tracker:

 
class ObjectTracker: public urbi::UObject 

public
  ObjectTracker(const std::string& n) 
    : urbi::UObject(n) 
  { 
    // Bind our constructor. 
    UBindFunction(ObjectTracker, init); 
  } 
  // Take our data source in our constructor. 
  void init(UVar& image) 
  { 
    UNotifyChange(image, &ObjectTracker::onImage); 
    // Bind our output variable. 
    UBindVar(ObjectTracker, val); 
  } 
  void onImage(UVar& src) 
  { 
    UBinary b = src; 
    // Processing here. 
    val = processing_result; 
  } 
  UVar val; 
}; 
UStart(ObjectTracker);  

The following urbiscript code would be used to initialize an ObjectTracker given a camera:

 
var tracker = ObjectTracker.new(camera.&val);  

An other component could then take the tracker output as its input.

Using this model, chains of processing elements can be created. Each time the UObject at the start of the chain updates, all the notifyChange will be called synchronously in cascade to update the state of the intermediate components.

4.7 Data-flow based programming: InputPort

Urbi provides a second and more standard way to perform data-flow programming. In this approach, inputs of a component are declared as local InputPort, and the binding between this InputPort and the output of another component is done in urbiscript using the >> operator between two UVar:

 
class ObjectTracker: public urbi::UObject 

  ObjectTracker(const std::string& n) 
    : urbi::UObject(n) 
  { 
    // Bind our constructor. 
    UBindFunction(ObjectTracker, init); 
    // Bind our input port. 
    UBindVar(ObjectTracker, input); 
    // NotifyChange on our own input port 
    UNotifyChange(input, &ObjectTracker::onImage); 
  } 
 
  // Init is empty. 
  void init() 
  { 
  } 
 
  // onImage is unchanged. 
  void onImage(UVar& src) 
  { 
    UBinary b = src; 
    // Processing here. 
    val = processing_result; 
  } 
 
  UVar val; 
 
  // Declare our input port. 
  InputPort input; 
}; 
UStart(ObjectTracker);  

In this model, linking the components is done in urbiscript:

 
var tracker = ObjectTracker.new(); 
camera.&val >> tracker.&input;  

4.7.1 Customizing data-flow links

The >> operator to establish a data-flow link between two UVar returns an object of type UConnection that can be used to customize the link.

This object is also present in the slot changeConnections of the source UVar.

Here is the list of UConnection slots:

The function uobjects.connectionStats() can be used to display the statistics of all the connections, and uobjects.resetConnectionStats() can be called to reset all statistics.

4.8 Timers

The API provides two methods to have a function called periodically:

4.9 The special case of sensor/actuator variables

In Urbi, a variable can have a different meaning depending on whether you are reading or writing it: you can use the same variable to represent the target value of an actuator and the current value measured by an associated sensor. This special mode is activated by the UObject defining the variable by calling UOwned after calling UBindVar. This call has the following effects:

4.10 Using Urbi variables

The C++ class UVar is used to represent any Urbi slot in C++. To bind the UVar to a specific slot, pass its name to the UVar constructor, or its init method. Once the UVar is bound, you can write any compatible type to it, and the new value will be visible in urbiscript. Similarly, you can cast the UVar (or use the as() method) to convert the current urbiscript value held to any compatible type.

Compatible types are the same as for bound functions (see Section 4.18).

 
// Set the camera format to 0 if it is 1. 
UVar v; 
v.init("camera""format"); 
if (v == 1) 
 v = 0;  

Some care must be taken in remote mode: changes on the variable coming from Urbi code or an other module can take time to propagate to the UVar. By default, all changes to the value will be sent to the remote UObject. To have more control on the bandwidth used, you can disable the automatic update by calling unnotify(). Then you can get the value on demand by calling UVar::syncValue().

 
UVar v("Global""x"); 
send("every|(100ms) Global.x = time,"); 
// At this point, v is updated approximately every 100 milliseconds. 
 
v.unnotify(); 
// At this point v is no longer updated. If v was the only UVar pointing to 
// ’Global.x’, the value is no longer transmitted. 
 
v.syncValue(); 
// The previous call will ask for the value of Global.x once, and block until 
// the value is written to v.  

You can read and write all the Urbi properties of an UVar by reading and writing the appropriate UProp object in the UVar.

4.11 Emitting events

The UEvent class can be used to create and emit urbiscript events. Instances are created and initialized exactly as UVar: either by using the UBindEvent macro, or by calling one of its constructors or the init function.

Once initialized, the emit function will trigger the emission of the associated urbiscript event. It can be called with any number of arguments, of any compatible type.

4.12 UObject and Threads

The UObject API is thread-safe in both plugin and remote mode: All API calls including operations on UVar can be performed from any thread.

4.13 Using binary types

Urbi can store binary objects of any type in a generic container, and provides specific structures for sound and images. The generic containers is called UBinary and is defined in the ‘urbi/ubinary.hh’ header. It contains an enum field type giving the type of the binary (UNKNOWN, SOUND or IMAGE), and an union of a USound and UImage struct containing a pointer to the data, the size of the data and type-specific meta-information.

4.13.1 UVar conversion and memory management

The UBinary manages its memory: when destroyed (or going out-of-scope), it frees all its allocated data. The USound and UImage do not.

Reading an UBinary from a UVar, and writing a UBinary, USound or UImage to an UVar performs a deep-copy of the data (by default, see below).

Reading a USound or UImage from an UVar directly will perform a shallow copy from the internal data. The structure content is only guaranteed to be valid until the function returns, and should not be modified.

4.13.2 Binary conversion

To convert between various sound and image formats, two functions are provided in the header ‘urbi/uconversion.hh’:

 
void urbi::convert(UImage& source, UImage& destination); 
void urbi::convert(USound& source, USound& destination);  

For those functions to work, destination must be filled correctly:

Consider this example of a sound algorithm requiring 8-bit mono input:

 
class SoundAlgorithm: public UObject 

public
  <...> 
  void init(); 
  void onData(UVar& v); 
  // We reuse the same USound for converted data to avoid reallocation. 
  USound convertedData; 

 
void SoundAlgorithm::init(UVar& dataSource) 

  // initialize convertedData 
  convertedData.data = 0; 
  convertedData.size = 0; // Let convert allocate for us 
  convertedData.soundFormat = SOUND_RAW; 
  convertedData.channels = 1; 
  convertedData.rate = 0; // Use sample rate of the source 
  convertedData.sampleSize = 8; 
  convertedData.sampleFormat = SAMPLE_UNSIGNED; 
  UNotifyChange(dataSource, &SoundAlgorithm::onData); 

 
void SoundAlgorithm::onData(UVar& v) 

  USound src = v; 
  convert(src, convertedData); 
  // Work on convertedData. 
}  

4.13.3 0-copy mode

In plugin mode, you can setup any UVar in 0-copy mode by calling setBypass(true). In this mode, binary data written to the UVar is not copied, but a reference is kept. As a consequence, the data is only available from within registered notifyChange callbacks. Those callbacks can use UVar::val() or cast the UVar to a UBinary & to retrieve the reference. Attempts to read the UVar from outside notifyChange will block until the UVar is updated again, and copy the value at this time.

An example will certainly clarify: Let us first declare an UObject that will generate binary data using 0-copy mode.

 
// Declare an UObject producing images in 0-copy optimized mode. 
class OptimizedImageSource: public UObject 

  <...> 
  public
    UVar val; 
    UBinary imageData; 
}; 
 
void OptimizedImageSource::init() 

  // Bind val 
  UBindVar(OptimizedImageSource, val); 
  // Mark it as bypass mode 
  val.setBypass(true); 
  // Start a timer. 
  USetUpdate(10); 

 
int OptimizedImageSource::update() 

  <Update imageData here> 
  // Notify all notifyChange callbacks without copying the data. 
  val = imageData; 
}  

Let us then declare an other component that will access this binary data without any copy:

 
class BinaryProcessor: public UObject 

  public
  void init(); 
  void onData(UVar& v); 
  InputPort binaryIn; 
}; 
 
void BinaryProcessor::init() 

  UBindVar(BinaryProcessor, binaryIn); 
  UNotifyChange(binaryIn, &BinaryProcessor::onData); 

 
void BinaryProcessor::onData(UVar& v) 

  const UBinary& b = v; 
  // If in urbiscript you connect the two components using: 
  //  OptimizedImageSource.&val >> BinaryProcessor.&binaryIn 
  // then b will be OptimizedImageSource.binaryData, not a copy. 
}  

Typing OptimizedImageSource.val in urbiscript will wait for the next update from OptimizedImageSource::update and copy the data at this point.

4.14 Direct Communication between UObjects

For modularity reasons, all interactions between UObjects should go through the various middleware communication mechanisms, mainly InputPort and UNotifyChange. But it is possible to access directly the C++ instance of an UObject:

4.15 Using hubs to group objects

Sometimes, you need to perform actions for a group of UObjects, for instance devices that need to be updated together. The API provides the UObjectHub class for this purpose. To create a hub, simply declare a subclass of UObjectHub, and register it by calling once the macro UStartHub (class-name). A single instance of this class will then be created upon server start-up. UObject instances can then register to this hub by calling URegister (hub-class-name). Timers can be attached to UObjectHub the same way as to UObject (see Section 4.8). A hub instance can be retrieved by calling getUObjectHub (string class-name). The hub also holds the list of registered UObject in its members attribute.

4.16 Sending urbiscript code

If you need to send urbiscript code to the server, the URBI() macro is available, as well as the send() function. You can either pass it a string, or directly Urbi code inside a double pair of parentheses:

 
send ("myTag:1+1;"); 
 
URBI (( at (myEvent?(var x)) { myTag:echo x; }; ));  

You can also use the call method to make an urbiscript function call:

 
// C++ equivalent of urbiscript ’System.someFunc(12, "foo");’ 
call("System""someFunc", 12, "foo");  

4.17 Using RTP transport in remote mode

By default, Urbi uses TCP connections for all communications between the engine and remote UObjects. Urbi also supports the UDP-based RTP protocol for more efficient transmission of updated variable values. RTP will provide a lower latency at the cost of possible packet loss, especially in bad wireless network conditions.

4.17.1 Enabling RTP

To enable RTP connections, both the engine and the remote-mode urbi-launch containing your remote UObject must load the RTP UObject. This can be achieved by passing urbi/rtp as an extra argument to both urbi-launch command lines (one for the engine, the other for your remote UObject).

Once done, all binary data transfer (like sound and image) in both directions will by default use a RTP connection.

4.17.2 Per-UVar control of RTP mode

You can control whether a specific UVar uses RTP mode by calling its useRTP(bool) function. Each binary-type UVar will have its own RTP connection, and all non-binary UVar will share one.

From urbiscript, you can also write to the rtp slot of each UVar. Existing notifies will be modified to use rtp if you set it to true.

4.18 Extending the cast system

4.18.1 Principle

The same cast system is used both for bound function’s arguments and return values, and for reading/writing UVar.

Should you want to add new type MyType to the system you must define two functions:

 
namespace urbi 

  void operator, (UValue& v, const MyType& t) 
  { 
    // Here you must fill v with the serialized representation of t. 
  } 
 
  template<> struct uvalue_caster<MyType> 
  { 
    MyType operator()(UValue& v) 
    { 
      // Here you must return a MyType made with the information in v. 
    } 
  } 
}  

Once done, you will be able without any other change to

4.18.2 Casting simple structures

The system provides facilities to serialize simple structures by value between C++ and urbiscript. This system uses two declarations of each structure, one in C++ and the other in Urbi, and maps between the two.

Here is a complete commented example to map a simple Point structure between urbiscript and C++.

 
struct Point 

  // Your struct must have a default constructor. 
  Point() 
    : x(0), y(0) 
  {} 
  double x, y; 
}; 
 
// Declare the structure to the cast system. First argument is the struct, 
// following arguments are the field names. 
URBI_REGISTER_STRUCT(Point, x, y);  

 
// Declare the urbiscript structure. It must be globally accessible, and 
// inheriting from UValueSerializable. 
class Global.Point: UValueSerializable 

  var x = 0; 
  var y = 0; 
 
  function init(var xx = 0, var yy = 0) 
  { 
    x = xx| 
    y = yy 
  }; 
 
  function asString() 
  { 
    "<%s, %s>" % [x, y] 
  }; 
}; 
// Add the class to Serializables to register it. 
var Serializables.Point = Point;  

Once done, you can call bound functions taking a C++ Point by passing them an urbiscript Point and exchange Point between both worlds through UVar read/write:

 
// This function can be bound using UBindFunction. 
Point MyObject::opposite(Point p) 

  return Point(-p.x, -p.y); 

 
// Writing a Point to an UVar is OK. 
void MyObject::writePoint(Point p) 

  UVar v(this"val"); 
  v = p; 

 
// Converting an UVar to a Point is easy. 
ufloat MyObject::xCoord() 

  UVar v(this"val"); 
  Point p; 
  // Fill p with content of v. 
  v.fill(p); 
  // Alternate for the above. 
  p = v.as<Point>(); 
  return v.x; 
}  

Chapter 5
The UObject Java API

The UObject Java API can be used to add new remote objects written in Java to the urbiscript language, and to interact from Java with the objects that are already defined. We cover the use cases of interfacing higher-level components (voice recognition, object detection…) with Urbi using Java.

The Java API defines the UObject class. To each instance of a Java class deriving from UObject will correspond an urbiscript object sharing some of its methods and attributes. The API provides methods to declare which elements of your object are to be shared. To share a variable with Urbi, you have to give it the type UVar. This type is a container that provides conversion and setter member functions for all types known to Urbi: double, java.lang.String, the binary-holding structures urbi.UBinary, urbi.USound and urbi.UImage, list types urbi.UList and dictionaries urbi.Dictionary. This type can also read from and write to the urbi.UValue class. The API provides methods to set up callbacks functions that will be notified when a variable is modified or read from urbiscript code. Instance methods of any prototype can be made accessible from urbiscript, providing all the parameter types and the return type can be converted to/from urbi.UValue.

The UObject Java API has the following limitations:

5.1 Compiling and running UObjects

UObjects can be compiled easily directly with the javac compiler, then you can create JAR archives using the jar tool.

In the following sections, we will try to create an uobject jar archive named ‘machine.jar’ from a set of two files (‘Machine.java’, ‘UMachine.java’.

In what follows, urbi-root denotes the top-level directory of your Urbi SDK package, see Section 16.2.

5.1.1 Compiling and running by hand

To compile your UObject you need to include in the classpath liburbijava.jar:

 
$ javac -cp urbi-root/share/sdk-remote/java/lib/liburbijava.jar:. \ 
  Machine.java UMachine.java 
$ jar -cvf machine.jar UMachine.class Machine.class 
added manifest 
adding: UMachine.class 
adding: Machine.class  

Then to run your uobject, you need to call java. We provide a main class called urbi.UMain in the liburbijava.jar archive. You can use this class to start your UObjects. This class takes the names of your uobjects jar files as argument. You also need to specify the lib folder of the urbi SDK into java.library.path:

 
$ java -Djava.library.path=urbi-root/lib                          \ 
    -cp urbi-root/share/sdk-remote/java/lib/liburbijava.jar       \ 
     urbi.UMain ./machine.jar 
urbi-launch: obeying to URBI_ROOT = /usr/local/gostai 
UObject: Urbi SDK version 2.3 rev. 3e93ec1 
Copyright (C) 2004-2010 Gostai S.A.S. 
 
Libport version urbi-sdk-2.3 rev. 66cb0ec 
Copyright (C) 2004-2010 Gostai S.A.S. 
UObject: Remote Component Running on 127.0.0.1 54000 
Kernel Version: 0 
[LibUObject] Registering function UMachine.init 1 into UMachine.init from UMachine 
[LibUObject] Pushing UMachine.init in function  

5.1.2 The umake-java and urbi-launch-java tools

umake-java can be used to compile Java UObjects. It will produce a JAR archive that you can use with urbi-launch-java.

You can give it a list of files to compile:

 
$ umake-java -q machine.uob/*.java -o machine.jar  

or directories in which C++ sources are looked for:

 
$ umake-java -q machine.uob -o machine.jar  

or finally, if you give no argument at all, the sources in the current directory:

 
cd machine.uob 
$ umake-java -q -o machine.jar  

To run your UObject then use urbi-launch-java (see Section 21.6):

 
$ urbi-launch-java machine.jar 
urbi-launch: obeying to URBI_ROOT = /usr/local/gostai 
UObject: Urbi SDK version 2.3 rev. 3e93ec1 
Copyright (C) 2004-2010 Gostai S.A.S. 
 
Libport version urbi-sdk-2.3 rev. 66cb0ec 
Copyright (C) 2004-2010 Gostai S.A.S. 
UObject: Remote Component Running on 127.0.0.1 54000 
Kernel Version: 0 
[LibUObject] Registering function UMachine.init 1 into UMachine.init from UMachine 
[LibUObject] Pushing UMachine.init in function  

5.2 Creating a class, binding variables and functions

Let’s illustrate those concepts by defining a simple object: adder. This object has one variable v, and a method add that returns the sum of this variable and its argument.

If you run this UObject and test it from Urbi it gives:

 
[00000102] *** ******************************************************** 
[00000102] *** Urbi SDK version 2.0 rev. 96a4b2f 
[00000102] *** Copyright (C) 2004-2010 Gostai S.A.S. 
[00000102] *** 
[00000102] *** This program comes with ABSOLUTELY NO WARRANTY. 
[00000102] *** It can be used under certain conditions. 
[00000102] *** Type ‘license;’ or ‘copyright;’ for more information. 
[00000102] *** 
[00000102] *** Check our community site: http://www.urbiforge.org. 
[00000102] *** ******************************************************** 
Adder; 
[00006783] Adder 
Adder.v; 
[00010871] 42 
Adder.add(-26); 
[00025795] 16 
Adder.add(-2.6); 
[00035411] 39.4  

To summarize:

5.3 Creating new instances

When you start an Urbi server, an object of each class registered with UStart is created with the same name as the class. New instances can be created from Urbi using the new method. For each instance created in Urbi, a corresponding instance of the Java object is created. You can get the arguments passed to the constructor by defining and binding a method named init with the appropriate number of arguments.

For example let’s add an Urbi constructor to our Adder class. We rewrite it as follow:

 
public class Adder extends UObject // must extends UObject 

  /// Register the class within urbi 
  static { UStart(Adder.class); } 
 
  /// Declare a variable v that will be accessible in Urbi 
  private UVar v = new UVar (); 
 
  /// Constructor 
  public Adder (String s) 
  { 
    super (s); 
    UBindFunction ("init"); 
  } 
 
  /// The init function is the constructor in Urbi. Here it takes 
  /// one argument that we use to initialize the ’v’ variable. 
  /// The init function must return an int of value 0 
  /// if all went OK. 
  public int init (double v_init) 
  { 
    /// Bind the variable v to Urbi 
    UBindVar (v, "v"); 
 
    /// Initialize our UVar v to the value given in the 
    /// constructor 
    v.setValue(v_init); 
 
    /// Bind the function add to Urbi 
    UBindFunction ("add"); 
 
    return 0; 
  } 
 
  public double add (double rhs) 
  { 
    /// Return the value of our UVar v (converted to double) 
    /// plus the value of the argument of the function. 
    return v.doubleValue () + rhs; 
  } 
}  

Now ’v’ and ’add’ are bound only when instance of the Adder object are constructed. We have added an ’init’ constructor with one parameter that we use to initialize the value of v. You can run this UObject and test it in Urbi to see the difference with the previous example. Here is what it gives:

 
[00000097] *** ******************************************************** 
[00000097] *** Urbi SDK version 2.0 rev. 96a4b2f 
[00000097] *** Copyright (C) 2004-2010 Gostai S.A.S. 
[00000097] *** 
[00000097] *** This program comes with ABSOLUTELY NO WARRANTY. 
[00000097] *** It can be used under certain conditions. 
[00000097] *** Type ‘license;’ or ‘copyright;’ for more information. 
[00000097] *** 
[00000097] *** Check our community site: http://www.urbiforge.org. 
[00000097] *** ******************************************************** 
Adder; 
[00010592] Adder 
Adder.v; 
[00013094:error] !!! 2.1-7: lookup failed: v 
var a = Adder.new(51); 
[00041405] object_13 
a.v; 
[00044742] 51 
a.add(10); 
[00054783] 61  

5.4 Binding functions

5.4.1 Simple binding

To bind the functions to Urbi, you can use:

 
void UBindFunction (Object obj, String method_name, String[] parameters_name)  
or one of the convenient version:
 
void UBindFunction (String method_name) 
void UBindFunctions(String ... method_names) 
void UBindFunction (Object obj, String method_name) 
void UBindFunctions (Object obj, String ... method_names)  

The first function takes as parameter the object containing the function (for now it is only possible to bind instance method, we do not handle static methods). The second parameter is the name of the function you want to bind. The third parameter is a list of the names if the types of the arguments. For example for the function add, in the previous Adder example, we could have used:

 
String[] params = { "double" }; 
UBindFunction (this"add", params);  

If in your UObject you have different names for each of your methods, then you can use the shorter versions of UBindFunction.

The functions you can bind must follow these rules:

5.5 Notification of a variable change or access

You can register a function that will be called each time a variable is modified by calling UNotifyChange, passing either an UVar or a variable name as first argument, and a member function of your UObject as second argument (and optionally a String array containing the name of the types of the parameters). The prototype for UNotifyChange is:

 
void UNotifyChange(String var_name, String method_name, String[] args_name); 
void UNotifyChange(String var_name, String method_name); 
void UNotifyChange(UVar v, String method_name, String[] args_name); 
void UNotifyChange(UVar v, String method_name);  

The callback function can take zero or one argument: an UVar pointing to the UVar being modified. And the callback function must return an int (the value returned is currently ignored in the actual implementation) or nothing at all (void). The notifyChange callback function is always called after the variable value is changed.

Notify functions can be unregistered by calling the unnotify function of the UVar class.

5.6 Timers

The API provides two methods to have a function called periodically:

5.7 Using Urbi variables

You can read or write any Urbi variable by creating an UVar passing the variable name to the constructor. Change the value by writing any compatible type to the UVar, and access the value by casting the UVar to any compatible type.

Note however that changes on the variable coming from Urbi code or an other module can take time to propagate to the UVar. You can read and write all the Urbi properties of an UVar by reading and writing the appropriate UProp object in the UVar.

5.8 Sending Urbi code

If you need to send Urbi code to the server, the send() function is available. You can pass it a string containing Urbi code:

 
send ("myTag:1+1;");  

You can also use the call method to make an urbiscript function call:

 
// Java equivalent of urbiscript ’System.someFunc(12, "foo");’ 
call("System""someFunc", new UValue(12), new UValue("foo"));  

These functions are member functions of the UObject class.

5.9 Providing a main class or not

We provide a main class, containing a main function, embedded in the liburbijava.jar file. This main class, called urbi.UMain is responsible for the loading of the liburbijava native library, and also for the registering of your uobjects.

5.10 Import the examples with Eclipse

We provide a sample Eclipse project configuration that you can import in Eclipse and use to create your own UObject Java.

We illustrate here how you can do this:

  1. Open Eclipse

    PIC

  2. Right click in the Package Explorer panel and select ’import’ (or go in File/import)

    PIC

  3. Select ’Existing Projects into Workspace’ in the opened windows
  4. Click ’Next’

    PIC

  5. Enter the path of the Urbi SDK on your computer
  6. Eclipse should find the .project file we provide and display the ’urbijava’ project
  7. Select the ’urbijava’ project and click ’Finish’

    PIC

The Java project is loaded. You can see the jar containing the liburbi (liburbijava.jar, storing the UObject Java API) which contains the urbi package, and also see the sources of the example we provide. We put them in the packages examples. You can inspire yourself from these examples to make your own UObjects. Here, we will see how to compile and run them in eclipse

NB: If Eclipse complains about errors in the source code, it can be that your compiler compliance level is two low. You have to set the compiler compliance level to Java 5 at least (Windows/Preferences/Java/Compiler).

PIC

5.11 Run the UObject Java examples

We provide a sample uobjectjava.launch files that you can load in eclipse to run the projects.

Chapter 6
Use Cases

6.1 Writing a Servomotor Device

Let’s write a UObject for a servomotor device whose underlying API is:

First our header. Our servo device provides an attribute named val, the standard Urbi name, and two ways to set PID gain: a method, and three variables.

 
class servo : public urbi::UObject // must inherit UObject 

public
  // the class must have a single constructor taking a string 
  servo(const std::string&); 
 
  // Urbi  constructor 
  void init(int id); 
 
  // main attribute 
  urbi::UVar val; 
 
  // position variables: 
  //  P gain 
  urbi::UVar P; 
  //  I gain 
  urbi::UVar I; 
  //  D gain 
  urbi::UVar D; 
 
  // callback for val change 
  void valueChanged(UVar& v); 
  //callback for val access 
  void valueAccessed(UVar& v); 
  // callback for PID change 
  void pidChanged(UVar& v); 
 
  // method to change all values 
  void setPID(int p, int i, int d); 
 
  // motor ID 
  int id_; 
};  

The constructor only registers init, so that our default instance servo does nothing, and can only be used to create new instances.

 
servo::servo (const std::string& s) 
  : urbi::UObject (s) 

   // register init 
   UBindFunction (servo, init); 
}  

The init function, called in a new instance each time a new Urbi instance is created, registers the four variables (val, P, I and D), and sets up callback functions.

 
// Urbi constructor. 
void 
servo::init (int id) 

  id_ = id; 
 
  if (!initialize (id)) 
    return 1; 
 
  UBindVar (servo, val); 
 
  // val is both a sensor and an actuator. 
  Uowned (val); 
 
  // Set blend mode to mix. 
  val.blend = urbi::UMIX; 
 
  // Register variables. 
  UBindVar (servo, P); 
  UBindVar (servo, I); 
  UBindVar (servo, D); 
 
  // Register functions. 
  UBindFunction (servo, setPID); 
 
  // Register callbacks on functions. 
  UNotifyChange (val, &servo::valueChanged); 
  UNotifyAccess (val, &servo::valueAccessed); 
  UNotifyChange (P, &servo::pidChanged); 
  UNotifyChange (I, &servo::pidChanged); 
  UNotifyChange (D, &servo::pidChanged); 
}  

Then we define our callback methods. servo::valueChanged will be called each time the val variable is modified, just after the value is changed: we use this method to send our servo commands. servo::valueAccessed is called just before the value is going to be read. In this function we request the current value from the servo, and set val accordingly.

 
// Called each time val is written to. 
void 
servo::valueChanged (urbi::UVar& v) 

  // v is a reference to our class member val: you can use both 
  // indifferently. 
  setPosition (id, (double)val); 

 
// Called each time val is read. 
void 
servo::valueAccessed (urbi::UVar& v) 

  // v is a reference to val. 
  val = getPosition (id); 
}  

servo::pidChanged is called each time one of the PID variables is written to. The function servo::setPID can be called directly from Urbi.

 
void 
servo::pidChanged (urbi::UVar& v) 

  setPID(id, (int)P, (int)I, (int)D); 

 
void 
servo::setPID (int p, int i, int d) 

  setPID (id, p, i, d); 
  P = p; 
  I = i; 
  D = d; 

 
// Register servo class to the Urbi kernel. 
UStart (servo);  

That’s it, compile this module, and you can use it within urbiscript:

 
// Create a new instance.  Calls init (1). 
headPan = new servo (1); 
 
// Calls setPID (). 
headPan.setPID (8,2,1); 
 
// Calls valueChanged (). 
headPan.val = 13; 
 
// Calls valueAccessed (). 
headPan.val * 12; 
 
// Periodically calls valueChanged (). 
headPan.val = 0 sin:1s ampli:20, 
 
// Periodically calls valueAccessed (). 
at (headPan.val < 0) 
  echo ("left");  

The sample code above has one problem: valueAccessed and valueChanged are called each time the value is read or written from Urbi, which can happen quite often. This is a problem if sending the actual command (setPosition in our example) takes time to execute. There are two solutions to this issue.

6.1.1 Caching

One solution is to remember the last time the value was read/written, and not apply the new command before a fixed time. Note that the kernel is doing this automatically for UOwned’d variables that are in a blend mode different than normal. So the easiest solution to the above problem is likely to set the variable to the mix blending mode. The unavoidable drawback is that commands are not applied immediately, but only after a small delay.

6.1.2 Using Timers

Instead of updating/fetching the value on demand, you can chose to do it periodically based on a timer. A small difference between the two API methods comes in handy for this case: the update() virtual method called periodically after being set up by USetUpdate(interval) is called just after one pass of Urbi code execution, whereas the timers set up by USetTimer are called just before one pass of Urbi code execution. So the ideal solution is to read your sensors in the second callback, and write to your actuators in the first. Our previous example (omitting PID handling for clarity) can be rewritten. The header becomes:

 
// Inherit from UObject. 
class servo : public urbi::UObject 

public
  // The class must have a single constructor taking a string. 
  servo (const std::string&) 
 
  // Urbi constructor. 
  void init (int id); 
 
  // Called periodically. 
  virtual int update (); 
  // Called periodically. 
  void getVal (); 
 
  // Our position variable. 
  urbi::UVar val; 
 
  // Motor ID. 
  int id_; 
};  

Constructor is unchanged, init becomes:

 
// Urbi constructor. 
void 
servo::init (int id) 

  id_ = id; 
 
  if (!initialize (id)) 
    return 0; 
 
  UBindVar (servo,val); 
  // Val is both a sensor and an actuator. 
  UOwned(val); 
 
  // Will call update () periodically. 
  USetUpdate(1); 
  // Idem for getVal (). 
  USetTimer (1, &servo::getVal); 
}  

valueChanged becomes update and valueAccessed becomes getVal. Instead of being called on demand, they are now called periodically. The period of the call cannot be lower than the value returned by Object.getPeriod; so you can set it to 0 to mean “as fast as is useful”.

6.2 Using Hubs to Group Objects

Now, suppose that, for our previous example, we can speed things up by sending all the servomotor commands at the same time, using the following method that takes two arrays of ids and positions.

 
void setPositions(int count, int* ids, double* positions);  

A hub is the perfect way to handle this task. The UObject header stays the same. We add a hub declaration:

 
class servohub : public urbi::UObjectHub 

public
  // The class must have a single constructor taking a string. 
  servohub (const std::string&); 
 
  // Called periodically. 
  virtual int update (); 
 
  // Called by servo. 
  void addValue (int id, double val); 
 
  int* ids; 
  double* vals; 
  int size; 
  int count; 
};  

servo::update becomes a call to the addValue method of the hub:

 
int 
servo::update() 

  ((servohub*)getUObjectHub ("servohub"))->addValue (id, (double)val); 
};  

The following line can be added to the servo init method, although it has no use in our specific example:

 
URegister(servohub);  

Finally, the implementation of our hub methods is:

 
servohub::servohub (const std::string& s) 
  : UObjectHub (s) 
  , ids   (0) 
  , vals  (0) 
  , size  (0) 
  , count (0) 

  // setup our timer 
  USetUpdate (1); 

 
int 
servohub::update () 

  // Called periodically. 
  setPositions (count, ids, vals); 
 
  // Reset position counter. 
  count = 0; 
 
  return 0; 

 
void 
servohub::addValue (int id, double val) 

  if (count + 1 < size) 
  { 
    // Allocate more memory. 
    ids = (int*) realloc (ids, (count + 1) * sizeof (int)); 
    vals = (double*) realloc (vals, (count + 1) * sizeof (double)); 
    size = count + 1; 
  } 
  ids[count] = id; 
  vals[count++] = val; 

 
UStartHub (servohub);  

Periodically, the update method is called on each servo instance, which adds commands to the hub arrays, then the update method of the hub is called, actually sending the command and resetting the array.

6.2.1 Alternate Implementation

Alternatively, to demonstrate the use of the members hub variable, we can entirely remove the update method in the servo class (and the USetUpdate() call in init), and rewrite the hub update method the following way:

 
int servohub::update() 

  //called periodically 
  for (UObjectList::iterator i = members.begin (); 
       i != members.end (); 
       ++i) 
    addValue (((servo*)*i)->id, (double)((servo*)*i)->val); 
  setPositions(count, ids, vals); 
  // reset position counter 
  count = 0; 
 
  return 0; 
}  

6.3 Writing a Camera Device

A camera device is an UObject whose val field is a binary object. The Urbi kernel itself doesn’t make any difference between all the possible binary formats and data type, but the API provides image-specific structures for convenience. You must be careful about memory management. The UBinary structure handles its own memory: copies are deep, and the destructor frees the associated buffer. The UImage and USound structures do not.

Let’s suppose we have an underlying camera API with the following functions:

Our device code can be written as follows:

 
// Inherit from UObject. 
class Camera : public urbi::UObject 

public
  // The class must have a single constructor taking a string. 
  Camera(const std::string&); 
 
  // Urbi constructor. Throw in case of error. 
  void init (int id); 
 
  // Our image variable and dimensions. 
  urbi::UVar val; 
  urbi::UVar width; 
  urbi::UVar height; 
 
  // Called on access. 
  void getVal (UVar&); 
 
  // Called periodically. 
  virtual int update (); 
 
  // Frame counter for caching. 
  int frame; 
  // Frame number of last access. 
  int accessFrame; 
  // Camera id. 
  int id_; 
  // Storage for last captured image. 
  UBinary bin; 
};  

The constructor only registers init:

 
Camera::Camera (const std::string& s) 
  : urbi::UObject (s) 
  , frame (0) 

  UBindFunction (Camera, init); 
}  

The init function binds the variable, a function called on access, and sets a timer up on update. It also initializes the UBinary structure.

 
void 
Camera::init (int id) 

  //urbi constructor 
  id_ = id; 
  frame = 0; 
  accessFrame = 0; 
 
  if (!initialize (id)) 
    throw std::runtime_error("Failed to initialize camera"); 
 
  UBindVar (Camera, val); 
  UBindVar (Camera, width); 
  UBindVar (Camera, height); 
  width = getWidth (id); 
  height = getHeight (id); 
 
  UNotifyAccess (val, &Camera::getVal); 
 
  bin.type = BINARY_IMAGE; 
  bin.image.width = width; 
  bin.image.height = height; 
  bin.image.imageFormat = IMAGE_RGB; 
  bin.image.size = width * height * 3; 
 
  // Call update () periodically. 
  USetUpdate (1); 
}  

The update function simply updates the frame counter:

 
int 
Camera::update () 

  ++frame; 
  return 0; 
}  

The getVal updates the camera value, only if it hasn’t already been called this frame, which provides a simple caching mechanism to avoid performing the potentially long operation of acquiring an image too often.

 
void 
Camera::getVal(urbi::UVar&) 

  if (frame == accessFrame) 
    return
 
  bin.image.data = getImage (id); 
  // Assign image to bin. 
  val = bin; 

 
UStart(Camera);  

The image data is copied inside the kernel when proceeding this way.

Be careful, suppose that we had created the UBinary structure inside the getVal method, our buffer would have been freed at the end of the function. To avoid this, set it to 0 after assigning the UBinary to the UVar.

6.3.1 Optimization in Plugin Mode

In plugin mode, it is possible to access the buffer used by the kernel by casting the UVar to a UImage. You can modify the content of the kernel buffer but no other argument.

6.4 Writing a Speaker or Microphone Device

Sound handling works similarly to image manipulation, the USound structure is provided for this purpose. The recommended way to implement a microphone is to fill the UObject val variable with the sound data corresponding to one kernel period. If you do so, the Urbi code loop tag:micro.val, will produce the expected result.

6.5 Writing a Softdevice: Ball Detection

Algorithms that require intense computation can be written in C++ but still be usable within Urbi: they acquire their data using UVar referencing other modules’ variables, and output their results to other UVar. Let’s consider the case of a ball detector device that takes an image as input, and outputs the coordinates of a ball if one is found.

The header is defined like:

 
class BallTracker : public urbi::UObject 

public
  BallTracker (const std::string&); 
  void init (const std::string& varname); 
 
  // Is the ball visible? 
  urbi::UVar visible; 
 
  // Ball coordinates. 
  urbi::UVar x; 
  urbi::UVar y; 
 };  

The constructor only registers init:

 
// The constructor registers init only. 
BallTracker::BallTracker (const::string& s) 
  : urbi::UObject (s) 

  UBindFunction (BallTracker, init); 
}  

The init function binds the variables and a callback on update of the image variable passed as a argument.

 
void 
BallTracker::init (const std::string& cameraval) 

  UBindVar (BallTracker, visible); 
  UBindVar (BallTracker, x); 
  UBindVar (BallTracker, y); 
  UNotifyChange (cameraval, &BallTracker::newImage); 
 
  visible = 0; 
}  

The newImage function runs the detection algorithm on the image in its argument, and updates the variables.

 
void 
BallTracker::newImage (urbi::UVar& v) 

  // Cast to UImage. 
  urbi::UImage i = v; 
  int px,py; 
  bool found = detectBall (i.data, i.width, i.height, &px, &py); 
 
  if (found) 
  { 
    visible = 1; 
    x = px / i.width; 
    y = py / i.height; 
  } 
  else 
    visible = 0; 
}  

Part II
urbiscript User Manual

About This Part

This part, also known as the “urbiscript tutorial”, teaches the reader how to program in urbiscript. It goes from the basis to concurrent and event-based programming. No specific knowledge is expected. There is no need for a C++ compiler, as UObject will not be covered here (see Part I). The reference manual contains a terse and complete definition of the Urbi environment (Part IV).
  Chapter 7 First Steps
 
First contacts with urbiscript.
  Chapter 8 Basic Objects, Value Model
 
A quick introduction to objects and values.
  Chapter 9 Flow Control Constructs
 
Basic control flow: if, for and the like.
  Chapter 10 Advanced Functions and Scoping
 
Details about functions, scopes, and lexical closures.
  Chapter 11 Objective Programming, urbiscript Object Model
 
A more in-depth introduction to object-oriented programming in urbiscript.
  Chapter 12 Functional Programming
 
Functions are first-class citizens.
  Chapter 13 Parallelism, Concurrent Flow Control
 
The urbiscript operators for concurrency, tags.
  Chapter 14 Event-based Programming
 
Support for event-driven concurrency in urbiscript.
  Chapter 15 Urbi for ROS Users
 
How to use ROS from Urbi, and vice-versa.

Chapter 7
First Steps

This section expects that you already know how to run urbi. If not, please first see Chapter 2.

This section introduces the most basic notions to write urbiscript code. Some aspects are presented only minimally. The goal of this section is to bootstrap yourself with the urbiscript language, to be able to study more in-depth examples afterward.

7.1 Comments

Commenting your code is crucial, so let’s start by learning how to do this in urbiscript. Comments are ignored by the interpreter, and can be left as documentation, reminder, …urbiscript supports C and C++ style comments:

 
1; // This is a C++ style comment. 
[00000000] 1 
 
2 + /* This is a C-style comment. */ 2; 
[00000000] 4 
 
"foo" /* You /* can /* nest */ */ comments. */ "bar"
[00000000] "foobar"  

Chapter 2 introduced some of the conventions used in this document: frames such as the previous one denote “urbiscript sessions”, i.e., dialogs between Urbi and you. The output is prefixed by a number between square brackets: this is the date (in milliseconds since the server was launched) at which that line was sent by the server. This is useful at occasions, since Urbi is meant to run many parallel commands. Since these timestamps are irrelevant in documentation, they will often be filled with zeroes. More details about the typesetting of this document (and the other kinds of frames) can be found in Chapter 34.

7.2 Literal values

Several special kinds of “values” can be entered directly with a specific syntax. They are called literals, or sometimes manifest values. We just met a first kind of literals: integers. There are several others, such as:

These examples highlight some points:

7.3 Function calls

You can call functions with the classical, mathematical notation.

 
cos(0); // Compute cosine 
[00000000] 1 
max(1, 3); // Get the maximum of the arguments. 
[00000000] 3 
max(1, 3, 4, 2); 
[00000000] 4  

Again, the result of the evaluation are printed out. You can see here that function in urbiscript can be variadic, that is, take different number of arguments, such as the max function. Let’s now try the echo function, that prints out its argument.

 
echo("Hello world!"); 
[00000000] *** Hello world!  

The server prints out Hello world!, as expected. Note that this output is still prepended with the time stamp. Since echo returns void, no evaluation result is printed.

7.4 Variables

Variables can be introduced with the var keyword, given a name and an initial value. They can be assigned new values with the = operator.

 
var x = 42; 
[00000000] 42 
echo(x); 
[00000000] *** 42 
x = 51; 
[00000000] 51 
x; 
[00000000] 51  

Note that, just as in C++, assignments return the (right-hand side) value, so you can write code like “x = y = 0”. The rule for valid identifiers is also the same as in C++: they may contain alphanumeric characters and underscores, but they may not start with a digit.

You may omit the initialization value, in which case it defaults to void.

 
var y; 
y; 
// Remember, the interpreter remains silent because void is printed out 
// as nothing.  You can convince yourself that y is actually void with 
// the following methods. 
y.asString; 
[00000000] "void" 
y.isVoid; 
[00000000] true  

7.5 Scopes

Scopes are introduced with curly brackets ({}). They can contain any number of statements. Variables declared in a scope only exist within this scope.

 

  var x = "test"
  echo(x); 
}; 
[00000000] *** test 
// x is no longer defined here 
x; 
[00000073:error] !!! lookup failed: x  

Note that the interpreter waits for the whole scope to be input to evaluate it. Also note the mandatory terminating semicolon after the closing curly bracket.

7.6 Method calls

Methods are called on objects with the dot (.) notation as in C++. Method calls can be chained. Methods with no arguments don’t require the parentheses.

 
0.cos(); 
[00000000] 1 
"a-b-c".split("-"); 
[00000000] ["a", "b", "c"] 
// Empty parentheses are optional 
"foo".length(); 
[00000000] 3 
"foo".length; 
[00000000] 3 
// Method call can be chained 
"".length.cos; 
[00000000] 1  

In obj.method, we say that obj is the target, and that we are sending him the method message.

7.7 Function definition

You know how to call routines, let’s learn how to write some. Functions can be declared thanks to the function keyword, followed by the comma separated, parentheses surrounded list of formal arguments, and the body between curly brackets.

 
// Define myFunction 
function myFunction() 

  echo("Hello world"); 
  echo("from my function!"); 
}; 
[00000000] function () { 
  echo("Hello world"); 
  echo("from my function!"); 
} 
 
// Invoke it 
myFunction(); 
[00000000] *** Hello world 
[00000000] *** from my function!  

Note the strange output after you defined the function. urbiscript seems to be printing the function you just typed in again. This is because a function definition evaluates to the freshly created function.

Functions are first class citizen: they are values, just as 0 or "foobar". The evaluation of a function definition yields the new function, and as always, the interpreter prints out the evaluation result, thus showing you the function again:

 
// Work in a scope. 

  // Define f 
  function f() 
  { 
    echo("f"
  }; 
  // This does not invoke f, it returns its value. 
  f; 
}; 
[00000000] function () { echo("f") } 

  // Define f 
  function f() 
  { 
    echo("Hello World"); 
  }; 
  // This actually calls f 
  f(); 
}; 
[00000000] *** Hello World  

Here you can see that f is actually a simple value. You can just evaluate it to see its value, that is, its body. By adding the parentheses, you can actually call the function. This is a difference with methods calling, where empty parentheses are optional: method are always evaluated, you cannot retrieve their functional value — of course, you can with a different construct, but that’s not the point here.

Since this output is often irrelevant, most of the time it is hidden in this documentation using the |; trick. When a statement is “missing”, an empty statement ({}) is inserted. So code|; is actually equivalent to code | {};, which means “run code, then run {} and return its value”. Since the value of {} is void, which is not displayed, this is a means to discard the result of a computation, and avoid that something is printed. Contrast the two following function definitions.

 
function sum(a, b, c) 

  return a + b + c; 
}; 
[00003553] function (var a, var b, var c) { return a.’+’(b).’+’(c) } 
function sum2(a, b, c) 

  return a + b + c; 
}|; 
sum(20, 2, 20); 
[00003556] 42  

The return keyword breaks the control flow of a function (similarly to the way break interrupts a loop) and returns the control flow to the caller. It accepts an optional argument, the value to return to the caller.

In urbiscript, if no return statement is executed, the value of the last expression is returned. Actually, refrained from using return when you don’t need it, it is both less readable (once you get used to this programming style), and less efficient (Listing 18.1.2).

 
function succ(i) { i + 1 }|; 
succ(50); 
[00000000] 51  

7.8 Conclusion

You’re now up and running with basic urbiscript code, and we can dive in details into advanced urbiscript code.

Chapter 8
Basic Objects, Value Model

In this section, we focus on urbiscript values as objects, and study urbiscript by-reference values model. We won’t study classes and actual objective programming yet, these points will be presented in Chapter 11.

8.1 Objects in urbiscript

An object in urbiscript is a rather simple concept: a list of slots. A slot is a value associated to a name. So an object is a list of slot names, each of which indexes a value — just like a dictionary.

 
// Create a fresh object with two slots. 
class Foo 

  var a = 42; 
  var b = "foo"
}; 
[00000000] Foo  

The localSlotNames method lists the names of the slots of an object (Object).

 
// Inspect it. 
Foo.localSlotNames; 
[00000000] ["a", "asFoo", "b", "type"]  

You can get an object’s slot value by using the dot (.) operator on this object, followed by the name of the slot.

 
// We now know the name of its slots. Let’s see their value. 
Foo.a; 
[00000000] 42 
Foo.b; 
[00000000] "foo"  

It’s as simple as this. The inspect method provides a convenient short-hand to discover an object (Object).

 
Foo.inspect; 
[00000000] *** Inspecting Foo 
[00000000] *** ** Prototypes: 
[00000000] ***   Object 
[00000000] *** ** Local Slots: 
[00000000] ***   a : Float 
[00000000] ***   asFoo : Code 
[00000000] ***   b : String 
[00000000] ***   type : String  

Let’s now try to build such an object. First, we want a fresh object to work on. In urbiscript, Object is the parent type of every object (in fact, since urbiscript is prototype-based, Object is the uppermost prototype of every object, but we’ll talk about prototypes later). An instance of object, is an empty, neutral object, so let’s start by instantiating one with the clone method of Object.

 
// Create the o variable as a fresh object. 
var o = Object.clone; 
[00000000] Object_0x00000000 
// Check its content 
o.inspect; 
[00006725] *** Inspecting Object_0x00000000 
[00006725] *** ** Prototypes: 
[00006726] ***   Object 
[00006726] *** ** Local Slots:  

As you can see, we obtain an empty fresh object. Note that it still inherits from Object features that all objects share, such as the localSlotNames method.

Also note how o is printed out: Object_, followed by an hexadecimal number. Since this object is empty, its printing is quite generic: its type (Object), and its unique identifier (every urbiscript object has one). Since these identifiers are often irrelevant and might differ between two executions, they are often filled with zeroes in this document.

We’re now getting back to our empty object. We want to give it two slots, a and b, with values 42 and "foo" respectively. We can do this with the setSlot method, which takes the slot name and its value.

 
o.setSlot("a", 42); 
[00000000] 42 
o.inspect; 
[00009837] *** Inspecting Object_0x00000000 
[00009837] *** ** Prototypes: 
[00009837] ***   Object 
[00009838] *** ** Local Slots: 
[00009838] ***   a : Float  

Here we successfully created our first slot, a. A good shorthand for setting slot is using the var keyword.

 
// This is equivalent to o.setSlot("b", "foo"). 
var o.b = "foo"
[00000000] "foo" 
o.inspect; 
[00072678] *** Inspecting Object_0x00000000 
[00072678] *** ** Prototypes: 
[00072679] ***   Object 
[00072679] *** ** Local Slots: 
[00072679] ***   a : Float 
[00072680] ***   b : String  

The latter form with var is preferred, but you need to know the name of the slot at the time of writing the code. With the former one, you can compute the slot name at execution time. Likewise, you can read a slot with a run-time determined name with the getSlot method, which takes the slot name as argument. The following listing illustrates the use of getSlot and setSlot to read and write slots whose names are unknown at code-writing time.

 
function set(object, name, value) 

  // We have to use setSlot here, since we don’t 
  // know the actual name of the slot. 
  return object.setSlot("x_" + name, value); 
}|; 
 
function get(object, name) 

  // We have to use getSlot here, since we don’t 
  // know the actual name of the slot. 
  return object.getSlot("x_" + name); 
}|; 
 
var x = Object.clone; 
[00000000] Object_0x42342448 
set(x, "foo", 0); 
[00000000] 0 
set(x, "bar", 1); 
[00000000] 1 
x.localSlotNames; 
[00000000] ["x_bar", "x_foo"] 
get(x, "foo"); 
[00000000] 0 
get(x, "bar"); 
[00000000] 1  

Right, now we can create fresh objects, create slots in them and read them afterward, even if their name is dynamically computed, with getSlot and setSlot. Now, you might wonder if there’s a method to update the value of the slot. Guess what, there’s one, and it’s named…updateSlot (originality award). Getting back to our o object, let’s try to update one of its slots.

 
o.a; 
[00000000] 42 
o.updateSlot("a", 51); 
[00000000] 51 
o.a; 
[00000000] 51  

Again, there’s a shorthand for updateSlot: operator =.

 
o.b; 
[00000000] "foo" 
// Equivalent to o.updateSlot("b", "bar") 
o.b = "bar"
[00000000] "bar" 
o.b; 
[00000000] "bar"  

Likewise, prefer the ’=’ notation whenever possible, but you’ll need updateSlot to update a slot whose name you don’t know at code-writing time.

Note that defining the same slot twice, be it with setSlot or var, is an error. The slot must be defined once with setSlot, and subsequent writes must be done with updateSlot.

 
var o.c = 0; 
[00000000] 0 
// Can’t redefine a slot like this 
var o.c = 1; 
[00000000:error] !!! slot redefinition: c 
// Okay. 
o.c = 1; 
[00000000] 1  

Finally, use removeLocalSlot to delete a slot from an object.

 
o.localSlotNames; 
[00000000] ["a", "b", "c"] 
o.removeLocalSlot("c"); 
[00000000] Object_0x00000000 
o.localSlotNames; 
[00000000] ["a", "b"]  

Here we are, now you can inspect and modify objects at will. Don’t hesitate to explore urbiscript objects you’ll encounter through this documentation like this. Last point: reading, updating or removing a slot which does not exist is, of course, an error.

 
o.d; 
[00000000:error] !!! lookup failed: d 
o.d = 0; 
[00000000:error] !!! lookup failed: d  

8.2 Methods

Methods in urbiscript are simply object slots containing functions. We made a little simplification earlier by saying that obj.slot is equivalent to obj.getSlot("slot"): if the fetched value is executable code such as a function, the dot form evaluates it, as illustrated below. Inside a method, this gives access to the target — as in C++. It can be omitted if there is no ambiguity with local variables.

 
var o = Object.clone; 
[00000000] Object_0x0 
// This syntax stores the function in the ’f’ slot of ’o’. 
function o.f () 

  echo("This is f with target " + this); 
  return 42; 
} |; 
// The slot value is the function. 
o.getSlot("f"); 
[00000001] function () { 
  echo("This is f with target ".’+’(this)); 
  return 42; 
} 
// Huho, the function is invoked! 
o.f; 
[00000000] *** This is f with target Object_0x0 
[00000000] 42 
// The parentheses are in fact optional. 
o.f(); 
[00000000] *** This is f with target Object_0x0 
[00000000] 42  

This was designed this way so as one can replace an attribute, such as an integer, with a function that computes the value. This enables to replace an attribute with a method without changing the object interface, since the parentheses are optional.

This implies that getSlot can be a better tool for object inspection to avoid invoking slots, as shown below.

 
// The ’empty’ method of strings returns whether the string is empty. 
"foo".empty; 
[00000000] false 
"".empty; 
[00000000] true 
// Using getSlot, we can fetch the function without calling it. 
"".getSlot("asList"); 
[00000000] function () { split("") }  

The asList function simply bounces the task to split. Let’s try getSlot’ing another method:

 
"foo".size; 
[00000000] 3 
"foo".getSlot("size"); 
[00000000] Primitive_0x422f0908  

The size method of String is another type of object: a Primitive. These objects are executable, like functions, but they are actually opaque primitives implemented in C++.

8.3 Everything is an object

If you’re wondering what is an object and what is not, the answer is simple: every single bit of value you manipulate in urbiscript is an object, including primitive types, types themselves, functions, …

 
var x = 0; 
[00000000] 0 
x.localSlotNames; 
[00000000] [] 
var x.slot = 1; 
[00000000] 1 
x.localSlotNames; 
[00000000] ["slot"] 
x.slot; 
[00000000] 1 
x; 
[00000000] 0  

As you can see, integers are objects just like any other value.

8.4 The urbiscript values model

We are now going to focus on the urbiscript value model, that is how values are stored and passed around. The whole point is to understand when variables point to the same object. For this, we introduce uid, a method that returns the target’s unique identifier — the same one that was printed when we evaluated Object.clone. Since uids might vary from an execution to another, their values in this documentation are dummy, yet not null to be able to differentiate them.

 
var o = Object.clone; 
[00000000] Object_0x100000 
o.uid; 
[00000000] "0x100000" 
42.uid; 
[00000000] "0x200000" 
42.uid; 
[00000000] "0x300000"  

Our objects have different uids, reflecting the fact that they are different objects. Note that entering the same integer twice (42 here) yields different objects. Let’s introduce new operators before diving in this concept. First the equality operator: ==. This operator is the exact same as C or C++’s one, it simply returns whether its two operands are semantically equal. The second operator is ===, which is the physical equality operator. It returns whether its two operands are the same object, which is equivalent to having the same uid. This can seem a bit confusing; let’s have an example.

 
var a = 42; 
[00000000] 42 
var b = 42; 
[00000000] 42 
a == b; 
[00000000] true 
a === b; 
[00000000] false  

Here, the == operator reports that a and b are equal — indeed, they both evaluate to 42. Yet, the === operator shows that they are not the same object: they are two different instances of integer objects, both equal 42.

Thanks to this operator, we can point out the fact that slots and local variables in urbiscript have a reference semantic. That is, when you defining a local variable or a slot, you’re not copying any value (as you would be in C or C++), you’re only making it refer to an already existing value (as you would in Ruby or Java).

 
var a = 42; 
[00000000] 42 
var b = 42; 
[00000000] 42 
var c = a; // c refers to the same object as a. 
[00000000] 42 
// a, b and c are equal: they have the same value. 
a == b && a == c; 
[00000000] true 
// Yet only a and c are actually the same object. 
a === b; 
[00000000] false 
a === c; 
[00000000] true  

So here we see that a and c point to the same integer, while b points to a second one. This a non-trivial fact: any modification on a will affect c as well, as shown below.

 
a.localSlotNames; 
[00000000] [] 
b.localSlotNames; 
[00000000] [] 
c.localSlotNames; 
[00000000] [] 
var a.flag; // Create a slot in a. 
a.localSlotNames; 
[00000000] ["flag"] 
b.localSlotNames; 
[00000000] [] 
c.localSlotNames; 
[00000000] ["flag"]  

Updating slots or local variables does not update the referenced value. It simply redirects the variable to the new given value.

 
var a = 42; 
[00000000] 42 
var b = a; 
[00000000] 42 
// b and a point to the same integer. 
a === b; 
[00000000] true 
// Updating b won’t change the referred value, 42, 
// it makes it reference a fresh integer with value 51. 
b = 51; 
[00000000] 51 
// Thus, a is left unchanged: 
a; 
[00000000] 42  

Understanding the two latter examples is really important, to be aware of what your variable are referring to.

Finally, function and method arguments are also passed by reference: they can be modified by the function.

 
function test(arg) 

  var arg.flag;  // add a slot in arg 
  echo(arg.uid); // print its uid 
} |; 
var x = Object.clone; 
[00000000] Object_0x1 
x.uid; 
[00000000] "0x1" 
test(x); 
[00000000] *** 0x1 
x.localSlotNames; 
[00000000] ["flag"]  

Beware however that arguments are passed by reference, and the behavior might not be what you may expected.

 
function test(arg) 

  // Updates the local variable arg to refer 1. 
  // Does not affect the referred value, nor the actual external argument. 
  arg = 1; 
} |; 
var x = 0; 
[00000000] 0 
test(x); 
[00000000] 1 
// x wasn’t modified 
x; 
[00000000] 0  

8.5 Conclusion

You should now understand the reference semantic of local variables, slots and arguments. It’s very important to keep them in mind, otherwise you will end up modifying variables you didn’t want, or change a copy of reference, failing to update the desired one.

Chapter 9
Flow Control Constructs

In this section, we’ll introduce some flow control structures that will prove handy later. Most of them are inspired by C/C++.

 9.1 if
 9.2 while
 9.3 for
 9.4 switch
 9.5 do

9.1 if

The if construct is the same has C/C++’s one. The if keyword is followed by a condition between parentheses and an expression, and optionally the else keyword and another expression. If the condition evaluates to true, the first expression is evaluated. Otherwise, the second expression is evaluated if present.

 
if (true) 
  echo("ok"); 
[00000000] *** ok 
if (false) 
  echo("ko"
else 
  echo("ok"); 
[00000000] *** ok  

The if construct is an expression: it has a value.

 
echo({ if (false) "a" else "b" }); 
[00000000] *** b  

9.2 while

The while construct is, again, the same as in C/C++. The while keyword is followed by a condition between parentheses and an expression. If the condition evaluation is false, the execution jumps after the while block; otherwise, the expression is evaluated and control jumps before the while block.

 
var x = 2; 
[00000000] 2 
while (x < 40) 

  x += 10; 
  echo(x); 
}; 
[00000000] *** 12 
[00000000] *** 22 
[00000000] *** 32 
[00000000] *** 42  

9.3 for

The for keyword supports different constructs, as in languages such as Java, C#, or even the forthcoming C++ revision.

The first construct is hardly more than syntactic sugar for a while loop.

 
for (var x = 2; x < 40; x += 10) 
  echo(x); 
[00000000] *** 2 
[00000000] *** 12 
[00000000] *** 22 
[00000000] *** 32  

The second construct allows to iterate over members of a collection, such as a list. The for keyword, followed by var, an identifier, a colon (or in), an expression and a scope, executes the scope for every element in the collection resulting of the evaluation of the expression, with the variable named with the identifier referring to the list members.

 
for (var e : [1, 2, 3]) { echo(e) }; 
[00000000] *** 1 
[00000000] *** 2 
[00000000] *** 3  

9.4 switch

The syntax of the switch construct is similar to C/C++’s one, except it works on any kind of object, not only integral ones. Comparison is done by semantic equality (operator ==). Execution will jump out of the switch-block after a case has been executed (no need to break). Also, contrary to C++, the whole construct has a value: that of the matching case.

 
switch ("bar"

  case "foo":  0; 
  case "bar":  1; 
  case "baz":  2; 
  case "qux":  3; 
}; 
[00000000] 1  

9.5 do

A do scope is a shorthand to perform several actions on an object.

 
var o1 = Object.clone; 
[00000000] Object_0x423a0708 
var o1.one = 1; 
[00000000] 1 
var o1.two = 2; 
[00000000] 2 
echo(o1.uid); 
[00000000] *** 0x423a0708  

The same result can be obtained with a short do scope, that redirect method calls to their target, as in the listing below. This is similar to the Pascal “with” construct. The value of the do-block is the target itself.

 
var o2 = Object.clone; 
[00000000] Object_0x42339e08 
// All the message in this scope are destined to o. 
do (o2) 

  var one = 1; // var is a shortcut for the setSlot 
  var two = 2; // message, so it applies on obj too. 
  echo(uid); 
}; 
[00000000] *** 0x42339e08 
[00000000] Object_0x42339e08  

Chapter 10
Advanced Functions and Scoping

This section presents advanced uses of functions and scoping, as well as their combo: lexical closures, which prove to be a very powerful tool.

10.1 Scopes as expressions

Contrary to other languages from the C family, scopes are expressions: they can be used where values are expected, just as 1 + 1 or "foo". They evaluate to the value of their last expression, or void if they are empty. The following listing illustrates the use of scopes as expressions. The last semicolon inside a scope is optional.

 
// Scopes evaluate to the value of their last expression. 
{ 1; 2; 3; }; 
[00000000] 3 
// They are expressions. 
echo({1; 2; 3}); 
[00000000] *** 3  

10.2 Advanced scoping

Scopes can be nested. Variables can be redefined in nested scopes. In this case, the inner variables hide the outer ones, as illustrated below.

 
var x = 0;   // Define the outer x. 
[00000000] 0 

  var x = 1; // Define an inner x. 
  x = 2;     // These refer to 
  echo(x);   // the inner x 
}; 
[00000000] *** 2 
x;           // This is the outer x again. 
[00000000] 0 

  x = 3;     // This is still the outer x. 
  echo(x); 
}; 
[00000000] *** 3 
x; 
[00000000] 3  

10.3 Local functions

Functions can be defined anywhere local variables can — that is, about anywhere. These functions’ visibility are limited to the scope they’re defined in, like variables. This enables for instance to write local helper functions like max2 in the example below.

 
function max3(a, b, c) // Max of three values 

  function max2(a, b) 
  { 
    if (a > b) 
      a 
    else 
      b 
  }; 
  max2(a, max2(b, c)); 
}|;  

10.4 Lexical closures

A closure is the capture by a function of a variable external to this function. urbiscript supports lexical closure: functions can refer to outer local variables, as long as they are visible (in scope) from where the function is defined.

 
function printSalaries(var rate) 

  var charges = 100; 
  function computeSalary(var hours) 
  { 
    // rate and charges are captured from the environment by closure. 
    rate * hours - charges 
  }; 
 
  echo("Alice’s salary is " + computeSalary(35)); 
  echo("Bob’s salary is " + computeSalary(30)); 
}|; 
printSalaries(15); 
[00000000] *** Alice’s salary is 425 
[00000000] *** Bob’s salary is 350  

Closures can also change captured variables, as shown below.

 
var a = 0; 
[00000000] 0 
var b = 0; 
[00000000] 0 
function add(n) 

  // a and b are updated by closure. 
  a += n; 
  b += n; 
  {} 
}|; 
add(25); 
add(25); 
add(1); 
a; 
[00000000] 51 
b; 
[00000000] 51  

Closure can be really powerful tools in some situations; they are even more useful when combined with functional programming, as described in Chapter 12.

Chapter 11
Objective Programming, urbiscript Object Model

This section presents object programming in urbiscript: the prototype-based object model of urbiscript, and how to define and use classes.

11.1 Prototype-Based Programming in urbiscript

You’re probably already familiar with class-based object programming, since this is the C++, Java, C# model. Classes and objects are very different entities. Classes and types are static entities that do not exist at run-time, while objects are dynamic entities that do not exist at compile time.

Prototype-based object programming is different: the difference between classes and objects, between types and values, is blurred. Instead, you have an object, that is already an instance, and that you might clone to obtain a new one that you can modify afterward. Prototype-based programming was introduced by the Self language, and is used in several popular script languages such as Io or JavaScript.

Class-based programming can be considered with an industrial metaphor: classes are molds, from which objects are generated. Prototype-based programming is more biological: a prototype object is cloned into another object which can be modified during its lifetime.

Consider pairs for instance (see Pair). Pairs hold two values, first and second, like an std::pair in C++. Since urbiscript is prototype-based, there is no pair class. Instead, Pair is really a pair (object).

 
Pair; 
[00000000] (nil, nil)  

We can see here that Pair is a pair whose two values are equal to nil — which is a reasonable default value. To get a pair of our own, we simply clone Pair. We can then use it as a regular pair.

 
var p = Pair.clone; 
[00000000] (nil, nil) 
p.first = "101010"
[00000000] "101010" 
p.second = true; 
[00000000] true 
p; 
[00000000] ("101010", true) 
Pair; 
[00000000] (nil, nil)  

Since Pair is a regular pair object, you can modify and use it at will. Yet this is not a good idea, since you will alter your base prototype, which alters any derivative, future and even past.

 
var before = Pair.clone; 
[00000000] (nil, nil) 
Pair.first = false; 
[00000000] false 
var after = Pair.clone; 
[00000000] (false, nil) 
before; 
[00000000] (false, nil) 
// before and after share the same first: that of Pair. 
assert(Pair.first === before.first); 
assert(Pair.first === after.first);  

11.2 Prototypes and Slot Lookup

In prototype-based language, is-a relations (being an instance of some type) and inheritance relations (extending another type) are simplified in a single relation: prototyping. You can inspect an object prototypes with the protos method.

 
var p = Pair.clone; 
[00000000] (nil, nil) 
p.protos; 
[00000000] [(nil, nil)]  

As expected, our fresh pair has one prototype, (nil, nil), which is how Pair displays itself. We can check this as presented below.

 
// List.head returns the first element. 
p.protos.head; 
[00000000] (nil, nil) 
// Check that the prototype is really Pair. 
p.protos.head === Pair; 
[00000000] true  

Prototypes are the base of the slot lookup mechanism. Slot lookup is the action of finding an object slot when the dot notation is used. So far, when we typed obj.slot, slot was always a slot of obj. Yet, this call can be valid even if obj has no slot slot, because slots are also looked up in prototypes. For instance, p, our clone of Pair, has no first or second slots. Yet, p.first and p.second work, because these slots are present in Pair, which is p’s prototype. This is illustrated below.

 
var p = Pair.clone; 
[00000000] (nil, nil) 
// p has no slots of its own. 
p.localSlotNames; 
[00000000] [] 
// Yet this works. 
p.first; 
// This is because p has Pair for prototype, and Pair has a ’first’ slot. 
p.protos.head === Pair; 
[00000000] true 
"first" in Pair.localSlotNames && "second" in Pair.localSlotNames; 
[00000000] true  

As shown here, the clone method simply creates an empty object, with its target as prototype. The new object has the exact same behavior as the cloned on thanks to slot lookup.

Let’s experience slot lookup by ourselves. In urbiscript, you can add and remove prototypes from an object thanks to addProto and removeProto.

 
// We create a fresh object. 
var c = Object.clone; 
[00000000] Object_0x1 
// As expected, it has no ’slot’ slot. 
c.slot; 
[00000000:error] !!! lookup failed: slot 
var p = Object.clone; 
[00000000] Object_0x2 
var p.slot = 0; 
[00000000] 0 
c.addProto(p); 
[00000000] Object_0x1 
// Now, ’slot’ is found in c, because it is inherited from p. 
c.slot; 
[00000000] 0 
c.removeProto(p); 
[00000000] Object_0x1 
// Back to our good old lookup error. 
c.slot; 
[00000000:error] !!! lookup failed: slot  

The slot lookup algorithm in urbiscript in a depth-first traversal of the object prototypes tree. Formally, when the s slot is requested from x:

Thus, slots from the last prototype added take precedence over other prototype’s slots.

 
var proto1 = Object.clone; 
[00000000] Object_0x10000000 
var proto2 = Object.clone; 
[00000000] Object_0x20000000 
var o = Object.clone; 
[00000000] Object_0x30000000 
o.addProto(proto1); 
[00000000] Object_0x30000000 
o.addProto(proto2); 
[00000000] Object_0x30000000 
// We give o an x slot through proto1. 
var proto1.x = 0; 
[00000000] 0 
o.x; 
[00000000] 0 
// proto2 is visited first during lookup. 
// Thus its "x" slot takes precedence over proto1’s. 
var proto2.x = 1; 
[00000000] 1 
o.x; 
[00000000] 1 
// Of course, o’s own slots have the highest precedence. 
var o.x = 2; 
[00000000] 2 
o.x; 
[00000000] 2  

You can check where in the prototype hierarchy a slot is found with the locateSlot method. This is a very handful tool when inspecting an object.

 
var p = Pair.clone; 
[00000000] (nil, nil) 
// Check that the ’first’ slot is found in Pair 
p.locateSlot("first") === Pair; 
[00000000] true 
// Where does locateSlot itself come from? Object itself! 
p.locateSlot("locateSlot"); 
[00000000] Object  

The prototype model is rather simple: creating a fresh object simply consists in cloning a model object, a prototype, that was provided to you. Moreover, you can add behavior to an object at any time with a simple addProto: you can make any object a fully functional Pair with a simple myObj.addProto(Pair).

11.3 Copy on Write

One point might be bothering you though: what if you want to update a slot value in a clone of your prototype?

Say we implement a simple prototype, with an x slot equal to 0, and clone it twice. We have three objects with an x slot, yet only one actual 0 integer. Will modifying x in one of the clone change the prototype’s x, thus altering the prototype and the other clone as well?

The answer is, of course, no, as illustrated below.

 
var proto = Object.clone; 
[00000000] Object_0x1 
var proto.x = 0; 
[00000000] 0 
var o1 = proto.clone; 
[00000000] Object_0x2 
var o2 = proto.clone; 
[00000000] Object_0x3 
// Are we modifying proto’s x slot here? 
o1.x = 1; 
[00000000] 1 
// Obviously not 
o2.x; 
[00000000] 0 
proto.x; 
[00000000] 0 
o1.x; 
[00000000] 1  

This work thanks to copy-on-write: slots are first duplicated to the local object when they’re updated, as we can check below.

 
// This is the continuation of previous example. 
 
// As expected, o2 finds "x" in proto 
o2.locateSlot("x") === proto; 
[00000000] true 
// Yet o1 doesn’t anymore 
o1.locateSlot("x") === proto; 
[00000000] false 
// Because the slot was duplicated locally 
o1.locateSlot("x") === o1; 
[00000000] true  

This is why, when we cloned Pair earlier, and modified the “first” slot of our fresh Pair, we didn’t alter Pair one all its other clones.

11.4 Defining Pseudo-Classes

Now that we know the internals of urbiscript’s object model, we can start defining our own classes.

But wait, we just said there are no classes in prototype-based object-oriented languages! That is true: there are no classes in the sense of C++, i.e., compile-time entities that are not objects. Instead, prototype-based languages rely on the existence of a canonical object (the prototype) from which (pseudo) instances are derived. Yet, since the syntactic inspiration for urbiscript comes from languages such as Java, C++ and so forth, it is nevertheless the class keyword that is used to define the pseudo-classes, i.e., prototypes.

As an example, we define our own Pair class. We just have to create a pair, with its first and second slots. For this we use the do scope described in Section 9.5. The listing below defines a new Pair class. The asString function is simply used to customize pairs printing — don’t give it too much attention for now.

 
var MyPair = Object.clone; 
[00000000] Object_0x1 
do (MyPair) 

  var first = nil; 
  var second = nil; 
  function asString () 
  { 
    "MyPair: " + first + ", " + second 
  }; 
}|; 
// We just defined a pair 
MyPair; 
[00000000] MyPair: nil, nil 
// Let’s try it out 
var p = MyPair.clone; 
[00000000] MyPair: nil, nil 
p.first = 0; 
[00000000] 0 
p; 
[00000000] MyPair: 0, nil 
MyPair; 
[00000000] MyPair: nil, nil  

That’s it, we defined a pair that can be cloned at will! urbiscript provides a shorthand to define classes as we did above: the class keyword.

 
class MyPair 

  var first = nil; 
  var second = nil; 
  function asString() { "(" + first + ", " + second + ")"; }; 
}; 
[00000000] (nil, nil)  

The class keyword simply creates MyPair with Object.clone, and provides you with a do (MyPair) scope. It actually also pre-defines a few slots, but this is not the point here.

It is also possible to specify a proto for the newly created “class”, using the same syntax as Java and C++:

 
class Top 

  var top = "top"
}; 
[00000000] Top 
 
class Bottom : Top 

  var bottom = "bottom"
}; 
[00000000] Bottom 
 
Bottom.new.top; 
[00000000] "top"  

For more details, see Section 22.1.6.8.

11.5 Constructors

As we’ve seen, we can use the clone method on any object to obtain an identical object. Yet, some classes provide more elaborate constructors, accessible by calling new instead of clone, potentially passing arguments.

 
var p = Pair.new("foo", false); 
[00000000] ("foo", false)  

While clone guarantees you obtain an empty fresh object inheriting from the prototype, new behavior is left to the discretion of the cloned prototype — although its behavior is the same as clone by default.

To define such constructors, prototypes only need to provide an init method, that will be called with the arguments given to new. For instance, we can improve our previous Pair class with a constructor.

 
class MyPair 

  var first = nil; 
  var second = nil; 
  function init(f, s) { first = f;   second = s;  }; 
  function asString() { "(" + first + ", " + second + ")"; }; 
}; 
[00000000] (nil, nil) 
MyPair.new(0, 1); 
[00000000] (0, 1)  

11.6 Operators

In urbiscript, operators such as +, && and others, are regular functions that benefit from a bit of syntactic sugar. To be more precise, a+b is exactly the same as a.’+’(b). The rules to resolve slot names apply too, i.e., the ’+’ slot is looked for in a, then in its prototypes.

The following example provides arithmetic between pairs.

 
class ArithPair 

  var first = nil; 
  var second = nil; 
  function init(f, s) { first = f;   second = s;  }; 
  function asString() { "(" + first + ", " + second + ")"; }; 
  function ’+’(rhs) { new(first + rhs.first, second + rhs.second); }; 
  function ’-’(rhs) { new(first - rhs.first, second - rhs.second); }; 
  function ’*’(rhs) { new(first * rhs.first, second * rhs.second); }; 
  function ’/’(rhs) { new(first / rhs.first, second / rhs.second); }; 
}; 
[00000000] (nil, nil) 
ArithPair.new(1, 10) + ArithPair.new(2, 20) * ArithPair.new(3, 30); 
[00000000] (7, 610)  

11.7 Properties

Slots should be understood as names to values. Several names may point to the same value (a phenomenon called aliasing). Enriching values is easy: provide them with new slots. Yet it is sometimes needed to define the behavior of the slot rather than the property of the value. This is the purpose of properties in urbiscript.

11.7.1 Features of Values

In following example, we attach some random property foo to the value pointed to by the slot x.

 
var x = 123; 
[00000000] 123 
var x.foo = 42; 
[00000000] 42  

If y is another slot to the value of x, then it provides the same foo feature:

 
var y = x; 
[00000000] 123 
y.foo; 
[00000000] 42  

If x is bound to a new object (e.g., 456), then the feature foo is no longer present, since it’s a feature of the value (i.e., 123), and not one of the slot (i.e., x).

 
x = 456; 
[00000000] 456 
x.foo; 
[00000000:error] !!! lookup failed: foo  

Of course, y, which is still linked to the original value (123), answers to queries to foo.

 
y.foo; 
[00000000] 42  

11.7.2 Features of Slots

If, on the contrary you want to attach a feature to the slot-as-a-name, rather than to the value it contains, use the properties. The syntax is slotName->propertyName.

 
x = 123; 
[00000000] 123 
x->foo = 42; 
[00000000] 42 
x->foo; 
[00000000] 42  

Copying the value contained by a slot does not propagate the properties of the slot:

 
y = x; 
[00000000] 123 
y->foo; 
[00000000:error] !!! property lookup failed: y->foo  

And if you assign a new value to a slot, the properties of the slot are preserved:

 
x = 456; 
[00000000] 456 
x->foo = 42; 
[00000000] 42  

Chapter 12
Functional Programming

urbiscript support functional programming through first class functions and lambda expressions.

12.1 First class functions

urbiscript has first class functions, i.e., functions are regular values, just like integers or strings. They can be stored in variables, passed as arguments to other functions, and so forth. For instance, you don’t need to write function object.f(){/* ... */} to insert a function in an object, you can simply use setSlot.

 
var o = Object.clone|; 
// Here we can use f as any regular value. 
o.setSlot("m1"function () { echo("Hello") })|; 
// This is strictly equivalent. 
var o.m2 = function () { echo("Hello") }|; 
o.m1; 
[00000000] *** Hello 
o.m2; 
[00000000] *** Hello  

This enables to write powerful pieces of code, like functions that take function as argument. For instance, consider the all function: given a list and a function, it applies the function to each element of the list, and returns whether all calls returned true. This enables to check very simply if all elements in a list verify a predicate.

 
function all(list, predicate) 

  for (var elt : list) 
    if (!predicate(elt)) 
      return false; 
  return true; 
}|; 
// Check if all elements in a list are positive. 
function positive(x) { x >= 0 }|; 
all([1, 2, 3], getSlot("positive")); 
[00000000] true 
all([1, 2, -3], getSlot("positive")); 
[00000000] false  

It turns out that all already exists: instead of all(listpredicate), use list.all(predicate), see RangeIterable.all.

12.2 Lambda functions

Another nice feature is the ability to write lambda functions, which are anonymous functions. You can create a functional value as an expression, without naming it, with the syntax shown below.

 
// Create an anonymous function 
function (x) {x + 1}|; 
// This enable to easily pass function 
// to our "all" function: 
[1, 2, 3].all(function (x) { x > 0}); 
[00000000] true  

In fact, the function construct we saw earlier is only a shorthand for a variable assignment.

 
// This ... 
function obj.f (/*...*/) {/*...*/}; 
// ... is actually a shorthand for: 
const var obj.f = function (/*...*/) {/* ... */};  

12.3 Lazy arguments

Most popular programming languages use strict arguments evaluation: arguments are evaluated before functions are called. Other languages use lazy evaluation: argument are evaluated by the function only when needed. In urbiscript, evaluation is strict by default, but you can ask a function not to evaluate its arguments, and do it by hand. This works by not specifying formal arguments. The function is provided with a call object that enables you to evaluate arguments.

 
// Note the lack of formal arguments specification 
function first 

  // Evaluate only the first argument. 
  call.evalArgAt(0); 
}|; 
first(echo("first"), echo("second")); 
[00000000] *** first 
function reverse 

  call.evalArgAt(1); 
  call.evalArgAt(0); 
}|; 
reverse(echo("first"), echo("second")); 
[00000000] *** second 
[00000000] *** first  

A good example are logic operators. Although C++ is a strict language, it uses a few logic operators. For instance, the logical and (&&) does not evaluate its right operand if the left operand is false (the result will be false anyway).

urbiscript logic operator mimic this behavior. The listing below shows how one can implement such a behavior.

 
function myAnd 

  if (call.evalArgAt(0)) 
    call.evalArgAt(1) 
  else 
    false; 
}|; 
 
function f() 

  echo("f executed"); 
  return true; 
}|; 
 
myAnd(false, f()); 
[00000000] false 
 
myAnd(true, f()); 
[00000000] *** f executed 
[00000000] true  

Chapter 13
Parallelism, Concurrent Flow Control

Parallelism is a major feature of urbiscript. So far, all we’ve seen already existed in other languages — although we tried to pick, mix and adapt features and paradigms to create a nice scripting language. Parallelism is one of the corner stones of its paradigm, and what makes it so well suited to high-level scripting of interactive agents, in fields such as robotics or AI.

13.1 Parallelism operators

For now, we’ve separated our different commands with a semicolon (;). There are actually four statement separators in urbiscript:

The example below demonstrates the use of & to launch two functions in parallel.

 
function test(name) 

  echo(name + ": 1"); 
  echo(name + ": 2"); 
  echo(name + ": 3"); 
} |; 
// Serialized executions 
test("left") ; test ("middle"); test ("right"); 
[00000000] *** left: 1 
[00000000] *** left: 2 
[00000000] *** left: 3 
[00000000] *** middle: 1 
[00000000] *** middle: 2 
[00000000] *** middle: 3 
[00000000] *** right: 1 
[00000000] *** right: 2 
[00000000] *** right: 3 
// Parallel execution 
test("left") & test("middle") & test ("right"); 
[00000000] *** left: 1 
[00000000] *** middle: 1 
[00000000] *** right: 1 
[00000000] *** left: 2 
[00000000] *** middle: 2 
[00000000] *** right: 2 
[00000000] *** left: 3 
[00000000] *** middle: 3 
[00000000] *** right: 3  

In this test, we see that the & runs its operands simultaneously.

The difference between “&” and “,” is rather subtle:

 
function test(name) 

  echo(name + ": 1"); 
  echo(name + ": 2"); 
  echo(name + ": 3"); 
}|; 
// Run test and echo("right") in parallel, 
// and wait until both are done before continuing 
test("left") & echo("right"); echo("done"); 
[00000000] *** left: 1 
[00000000] *** right 
[00000000] *** left: 2 
[00000000] *** left: 3 
[00000000] *** done 
// Run test in background, then both echos without waiting. 
test("left") , echo("right"); echo("done"); 
[00000000] *** left: 1 
[00000000] *** right 
[00000000] *** left: 2 
[00000000] *** done 
[00000000] *** left: 3  

That’s about all there is to say about these operators. Although they’re rather simple, they are really powerful and enables you to include parallelism anywhere at no syntactical cost.

13.2 Detach

The Control.detach function backgrounds the execution of its argument. Its behavior is the same as the comma (,) operator, except that the execution is completely detached, and not waited for at the end of the scope.

 
function test() 

  // Wait for one second, and echo "foo". 
  detach({sleep(1s); echo("foo")}); 
}|; 
test(); 
echo("Not blocked"); 
[00000000] Job<shell_4> 
[00000000] *** Not blocked 
sleep(2s); 
echo("End of sleep"); 
[00001000] *** foo 
[00002000] *** End of sleep  

13.3 Tags for parallel control flows

A Tag is a multipurpose code execution control and instrumentation feature. Any chunk of code can be tagged, by preceding it with a tag and a colon (:). Tag can be created with Tag.new(name). Naming tags is optional, yet it’s a good idea since it will be used for many features. The example below illustrates how to tag chunks of code.

 
// Create a new tag 
var mytag = Tag.new("name"); 
[00000000] Tag<name> 
// Tag the evaluation of 42 
mytag: 42; 
[00000000] 42 
// Tag the evaluation of a block. 
mytag: { "foo"; 51 }; 
[00000000] 51 
// Tag a function call. 
mytag: echo("tagged"); 
[00000000] *** tagged  

You can use tags that were not declared previously, they will be created implicitly (see below). However, this is not recommended since tags will be created in a global scope, the Tag object. This feature can be used when inputting test code in the top level to avoid bothering to declare each tag, yet it is considered poor practice in regular code.

 
// Since mytag is not declared, this will first do: 
// var Tag.mytag = Tag.new("mytag"); 
mytag : 42; 
[00000000] 42  

So you can tag code, yet what’s the use? One of the primary purpose of tags is to be able to control the execution of code running in parallel. Tags have a few control methods (see Tag):

freeze
Suspend execution of all tagged code.
unfreeze
Resume execution of previously frozen code.
stop
Stop the execution of the tagged code. The flows of execution that where stopped jump immediately at the end of the tagged block.
block
Block the execution of the tagged code, that is:
  • Stop it.
  • When an execution flow encounters the tagged block, it simply skips it.

You can think of block like a permanent stop.

unblock
Stop blocking the tagged code.

The three following examples illustrate these features.

 
// Launch in background (using the comma) code that prints "ping" 
// every second.  Tag it to keep control over it. 
mytag: 
  every (1s) 
    echo("ping"), 
sleep(2.5s); 
[00000000] *** ping 
[00001000] *** ping 
[00002000] *** ping 
// Suspend execution 
mytag.freeze; 
// No printing anymore 
sleep(1s); 
// Resume execution 
mytag.unfreeze; 
sleep(1s); 
[00007000] *** ping  

 
// Now, we print out a message when we get out of the tag. 

  mytag: 
    every (1s) 
      echo("ping"); 
  // Execution flow jumps here if mytag is stopped. 
  echo("Background job stopped")| 
}, 
sleep(2.5s); 
[00000000] *** ping 
[00001000] *** ping 
[00002000] *** ping 
// Stop the tag 
mytag.stop; 
[00002500] *** Background job stopped 
// Our background job finished. 
// Unfreezing the tag has no effect. 
mytag.unfreeze;  

 
// Now, print out a message when we get out of the tag. 
loop 

  echo("ping"); sleep(1s); 
  mytag: { echo("pong"); sleep(1s); }; 
}, 
sleep(3.5s); 
[00000000] *** ping 
[00001000] *** pong 
[00002000] *** ping 
[00003000] *** pong 
 
// Block printing of pong. 
mytag.block; 
sleep(3s); 
 
// The second half of the while isn’t executed anymore. 
[00004000] *** ping 
[00005000] *** ping 
[00006000] *** ping 
 
// Reactivate pong 
mytag.unblock; 
sleep(3.5s); 
[00008000] *** pong 
[00009000] *** ping 
[00010000] *** pong 
[00011000] *** ping  

13.4 Advanced example with parallelism and tags

In this section, we implement a more advanced example with parallelism.

The listing below presents how to implement a timeOut function, that takes code to execute and a timeout as arguments. It executes the code, and returns its value. However, if the code execution takes longer than the given timeout, it aborts it, prints "Timeout!" and returns void. In this example, we use:

 
// timeout (Code, Duration). 
function timeOut 

  // In background, launch a timeout job that waits 
  // for the given duration before aborting the function. 
  // call.evalArgAt(1) is the second argument, the duration. 
  { 
    sleep(call.evalArgAt(1)); 
    echo("Timeout!"); 
    return; 
  }, 
  // Run the Code and return its value. 
  return call.evalArgAt(0); 
} |; 
timeOut({sleep(1s); echo("On time"); 42}, 2s); 
[00000000] *** On time 
[00000000] 42 
timeOut({sleep(2s); echo("On time"); 42}, 1s); 
[00000000] *** Timeout!  

Chapter 14
Event-based Programming

When dealing with highly interactive agent programming, sequential programming is inconvenient. We want to react to external, random events, not execute code linearly with a predefined flow. urbiscript has a strong support for event-based programming.

14.1 Watchdog constructs

The first construct we will study uses the at keyword. Given a condition and a statement, at will evaluate the statement each time the condition becomes true. That is, when a rising edge occurs on the condition.

 
var x = 0; 
[00000000] 0 
at (x > 5) 
  echo("ping"); 
x = 5; 
[00000000] 5 
// This triggers the event. 
x = 6; 
[00000000] 6 
[00000000] *** ping 
// Does not trigger, since the condition is already true. 
x = 7; 
[00000000] 7 
// The condition becomes false here. 
x = 3; 
[00000000] 3 
 
x = 10; 
[00000000] 10 
[00000000] *** ping  

An onleave block can be appended to execute an expression when the expression becomes false — that is, on falling edges.

 
var x = false; 
[00000000] false 
at (x) 
  echo("x"
onleave 
  echo("!x"); 
x = true; 
[00000000] true 
[00000000] *** x 
x = false; 
[00000000] false 
[00000000] *** !x  

See Listing 22.10.1 for more details on at statements.

The whenever construct is similar to at, except the expression evaluation is systematically restarted when it finishes as long as the condition stands true.

 
var x = false; 
[00000000] false 
whenever (x) 

  echo("ping"); 
  sleep(1s); 
}; 
x = true; 
[00000000] true 
sleep(3s); 
// Whenever keeps triggering 
[00000000] *** ping 
[00001000] *** ping 
[00002000] *** ping 
x = false; 
[00002000] false 
// Whenever stops triggering  

Just like at has onleave, whenever has else: the given expression is evaluated as long as the condition is false.

 
var x = false; 
[00002000] false 
whenever (x) 

  echo("ping"); 
  sleep(1s); 

else 

  echo("pong"); 
  sleep(1s); 
}; 
sleep (3s); 
[00000000] *** pong 
[00001000] *** pong 
[00002000] *** pong 
x = true; 
[00003000] true 
sleep (3s); 
[00003000] *** ping 
[00004000] *** ping 
[00005000] *** ping 
x = false; 
[00006000] false 
sleep (2s); 
[00006000] *** pong 
[00007000] *** pong  

14.2 Events

In addition to monitoring an expression with a watchdog, urbiscript enables you to define events that can be caught with the at and whenever constructs we saw earlier. You can create events by instantiating the Event prototype. They can then be emitted with the ! keyword.

14.2.1 Emitting Events

 
var myEvent = Event.new; 
[00000000] Event_0xb5579008 
at (myEvent?) 
  echo("ping"); 
myEvent!; 
[00000000] *** ping 
// events work well with parallelism 
myEvent! & myEvent!; 
[00000000] *** ping 
[00000000] *** ping  

Both at and whenever have the same behavior on punctual events. However, if you emit an event for a given duration, whenever will keep triggering for this duration, contrary to at.

 
var myEvent = Event.new; 
[00000000] Event_0xb558a588 
whenever (myEvent?) 

  echo("ping (whenever)")| 
  sleep(200ms) 
}; 
at (myEvent?) 

  echo("ping (at)")| 
  sleep(200ms) 
}; 
// Emit myEvent for .3 second. 
myEvent!  300ms; 
[00000000] *** ping (whenever) 
[00000100] *** ping (whenever) 
[00000000] *** ping (at)  

14.2.2 Emitting events with a payload

Events behave very much like “channels”: listeners use at or whenever, and producers use !. Fortunately, the messages can include a payload, i.e., something sent in the “message”. The Event then behaves very much like an identifier of the message type. To send/catch the payload, just pass arguments to ! and ?:

 
var event = Event.new; 
[00000000] Event_0x0 
 
at (event?(var payload)) 
  echo("received: " + payload) 
onleave 
  echo("had received: " + payload); 
 
event!(1); 
[00000008] *** received: 1 
[00000009] *** had received: 1 
 
event!(["string", 124]); 
[00000010] *** received: ["string", 124] 
[00000011] *** had received: ["string", 124]  

Like functions, events have an arity, i.e., they depend on the number of arguments: at (event?(arg)) will only match emissions whose payload contain exactly one argument, i.e., event!(arg).

 
// Too many arguments. 
event!(1, 2); 
 
// Not enough arguments. 
event!; 
event!();  

Event handlers that do not specify their arity (i.e., without parentheses) match event emissions of any arity.

 
at (event?) 
  echo("received an event"
onleave 
  echo("had received an event"); 
 
event!; 
[00000014] *** received an event 
[00000015] *** had received an event 
 
event!(1); 
[00000016] *** received: 1 
[00000017] *** had received: 1 
[00000018] *** received an event 
[00000019] *** had received an event 
 
event!(1, 2); 
[00000020] *** received an event 
[00000021] *** had received an event  

Actually, the feature is much more powerful than this: full pattern matching applies, as with the switch/case construct.

 
var e = Event.new|; 
 
at (e?) 
  echo("e"); 
 
at (e?(var x)) 
  echo("e(x)"); 
 
at (e?(1)) 
  echo("e(1)"); 
 
at (e?(var x) if x.isA(Float) && x % 2) 
  echo("e(odd)"); 
 
// Payload must be a list of three members, the first two being 1 and 2, and 
// the third one being greater than 2, when converted as a Float. 
at (e?([1, 2, var x]) if 2 < x.asFloat) 
  echo("e([1, 2, x = %s])" % x); 
 
e!; 
[00000845] *** e 
 
e!(0); 
[00011902] *** e 
[00011902] *** e(x) 
 
e!(1); 
[00023327] *** e 
[00023327] *** e(x) 
[00023327] *** e(1) 
[00023327] *** e(odd) 
 
e!([1, 2, 1]); 
[00024327] *** e 
[00024327] *** e(x) 
 
e!([1, 2, 3]); 
[00025327] *** e 
[00025327] *** e(x) 
[00025327] *** e([1, 2, x = 3]) 
 
e!([1, 2, "4"]); 
[00026327] *** e 
[00026327] *** e(x) 
[00026327] *** e([1, 2, x = 4])  

Chapter 15
Urbi for ROS Users

This chapter extends the ROS official tutorials 1 . Be sure to complete this tutorial before reading this document.

15.1 Communication on topics

First we will take back examples about topics; make sure that talker and listener in the ‘beginner_tutorial’ package are compiled. You can recompile it with the following command:

 
$ rosmake beginner_tutorial  

15.1.1 Starting a process from Urbi

To communicate with ROS components, you need to launch them. You can do it by hand, or ask Urbi to do it for you. To launch new processes through Urbi, we will use the class Process.

Let’s say we want to start roscore, and the talker of the beginner tutorial. Open an Urbi shell by typing the command ‘rlwrap urbi -i’. Here rlwrap makes ‘urbi -i’ acts like a shell prompt, with features like line editing, history, …

 
var core = Process.new("roscore", []); 
[00000001] Process roscore 
var talker = Process.new("rosrun", ["beginner_tutorial""talker"]); 
[00000002] Process rosrun 
core.run; 
talker.run;  

At this point, the processes are launched. The first argument of Process.new is the name of the command to launch, the second is a list of arguments.

Then you can check the status of the processes, get their stdout/stderr buffers, kill them in urbiscript (see Process).

15.1.2 Listening to Topics

First you need to make sure that roscore is running, and the ROS module is loaded correctly:

 
Global.hasLocalSlot("Ros"); 
[00016931] true  

Then we can get the list of launched nodes:

 
Ros.nodes;  

This returns a Dictionary with the name of the node as key, and a dictionary with topics subscribed, topics advertised, topics advertised as value.

We can check that our talker is registered, and on which channel it advertises:

 
// Get the structure. 
// "|;" is an idiom to discard the display of the return value. 
var nodes = Ros.nodes|; 
 
// List of nodes (keys). 
nodes.keys; 
[00000002] ["/rosout", "/urbi_1273060422295250703", "/talker"] 
 
// Details of the node "talker". 
nodes["talker"]["publish"]; 
[00000003] ["/rosout", "/chatter"]  

Here we see that this node advertises ‘/rosout’ and ‘/chatter’. Let’s subscribe to ‘/chatter’:

 
// Initialize the subscription object. 
var chatter = Ros.Topic.new("/chatter")|; 
// Subscribe. 
chatter.subscribe; 
// This is the way we are called on new message. 
var chatTag = Tag.new|; 
chatTag: at (chatter.onMessage?(var e)) 
  // This will be executed on each message. 
  echo(e);  

In this code, e is a Dictionary that follows the structure of the ROS message. Here is an example of what this code produces:

 
[00000004] *** ["data" => "Hello there! This is message [4]"] 
[00000005] *** ["data" => "Hello there! This is message [5]"] 
[00000006] *** ["data" => "Hello there! This is message [6]"]  

We can also get a template for the message structure on this channel with:

 
chatter.structure; 
[00000007] ["data" => ""]  

To stop temporarily the Global.echo, we take advantages of tags (Section 13.3), by doing chatTag.freeze. Same thing goes with unfreeze. Of course you could also call chatter.unsubscribe, which unsubscribes you completely from this channel.

15.1.3 Advertising on Topics

To advertise a topic, this is roughly the same procedure.

15.1.3.1 Simple Talker

Here is a quick example:

 
// Initialize our object. 
var talker = Ros.Topic.new("/chatter")|; 
// Advertise (providing the ROS Type of this topic). 
talker.advertise("std_msgs/String"); 
 
// Get a template of our structure. 
var msg = talker.structure.new; 
msg["data"] = "Hello ROS world"|; 
talker << msg;  

We have just sent our first message to ROS, here if you launch the chatter, you will be able to get the message we have just sent.

The << operator is an convenient alias for Ros.Topic.publish.

15.1.3.2 Turtle Simulation

Now we are going to move the turtle with Urbi. First let’s launch the turtle node:

 
var turtle = Process.new("rosrun", ["turtlesim""turtlesim_node"])|; 
turtle.run;  

Ros.topics shows that this turtle subscribes to a topic ‘/turtle1/command_velocity’. Let’s advertise on it:

 
var velocity = Ros.Topic.new("/turtle1/command_velocity")|; 
velocity.advertise("turtlesim/Velocity"); 
velocity.structure; 
[00000001] ["linear" => 0, "angular" => 0]  

Now we want to have it moving in circle with a small sinusoid wave. This goes in two step. First, we set up the infrastructure so that changes in Urbi are seamlessly published in ROS.

 
// Get our template structure. 
var m = velocity.structure.new |; 
m["linear"] = 0.8 |; 
var angular = 0 |; 
// Every time angular is changed, we send a message. 
at (angular->changed?) 

  m["angular"] = angular; 
  velocity << m 
};  

In the future Urbi will provide helping functions to spare the user from the need to perform this “binding”. But once this binding done, all the features of urbiscript can be used transparently.

For instance we can assign a sinusoidal trajectory to ‘angular’, which results in the screen-shot on the right-hand side.

 
// For 20 seconds, bind "angular" to a sine. 
timeout (20s) 
  angular = 0.3 sin: 2s ampli: 2;  

Every time angular is changed, a new message is sent on the Topic ‘/turtle1/command_velocity’, thus updating the position of the turtle. After 20 seconds the command is stopped.

PIC

Alternatively, Tags could have been used to get more control over the trajectory:

 
// A Tag to control the following endless statement. 
var angTag = Tag.new|; 
 
angTag: 
  // Bind "angular" to a trajectory. 
  // Put in background thanks to ",", since this statement is never ending. 
  angular = 0.3 sin: 2s ampli: 2, 
 
// Leave 20 seconds to the turtle... 
sleep(20s); 
 
// before freezing it. 
angTag.freeze;  

We won’t cover this code in details, but the general principle is that angular is updated every 20ms with the values of a sinusoid wave trajectory with 0.3 as average value, 2 seconds for the period and 2 for the amplitude. See TrajectoryGenerator for more information. After 20 seconds the tag is frozen, pausing the trajectory generation and the at.

15.2 Using Services

Services work the same way topics do, with minor differences.

Let’s take back the turtle simulation example (Section 15.1.3.2). Then we can list the available services, and filter out loggers:

 
var logger = Regexp.new("(get|set)_logger") |; 
var services = Ros.services.keys |; 
for (var s in services) 
  if (s not in logger) 
    echo(s); 
[00000001] *** "/clear" 
[00000001] *** "/kill" 
[00000001] *** "/turtle1/teleport_absolute" 
[00000001] *** "/turtle1/teleport_relative" 
[00000001] *** "/turtle1/set_pen" 
[00000001] *** "/reset" 
[00000001] *** "/spawn"  

The closure construct allows us to keep access to the local variables, here logger.

Now there is a service called ‘/spawn’; to initialize it:

 
var spawn = Ros.Service.new("/spawn", false) |; 
waituntil(spawn.initialized);  

The new function takes the service name as first argument, and as second argument whether the connection should be kept alive.

Since the creation of this object checks the service name, you should wait until initialized is true to use this service. You can also see the structure of the request with spawn.reqStruct, and the structure of the response with spawn.resStruct.

Now let’s spawn a turtle called Jenny, at position (4, 4).

 
var req = spawn.reqStruct.new |; 
req["x"] = 4 | 
req["y"] = 4 | 
req["name"] = "Jenny" |; 
spawn.request(req); 
[00000001] ["name" => "Jenny"]  

15.3 Image Publisher from ROS to Urbi

This section will use topics manipulation with advertising and subscription. Be sure to understand these topics before doing this tutorial.

Requirements You have to finish the image Publisher/Subscriber tutorial (http://www.ros.org/wiki/image_transport/Tutorials) before doing this tutorial.

First, we will make a ROS Publisher and subscribe to it with Urbi. Make sure that Publisher ‘learning_image_transport’ package is compiled:

 
$ rosmake learning_image_transport  

We will also run urbi with a network connection opened (e.g., on port 54000) to allow urbi-image (Section 21.4) to connect to it.

 
$ urbi --host=127.0.0.1 --port=54000 -- -f  

Also, you have to run roscore to communicate with ROS.

 
var core = Process.new("roscore", []); 
[00000001] Process roscore 
core.run;  

Run the Publisher The Publisher is a process that will send a image and wait for a Subscriber to get it.

 
// In this example the image is in the current directory. 
var publisher = 
  Process.new("rosrun"
              ["learning_image_transport""my_publisher""test.jpg"]); 
[0000002] Process rosrun 
publisher.run;  

Using a camera to display By default, urbi-image displays the images that are available via the camera device (see Section 21.4). To simplify the setup, let’s define a pseudo camera which will store the data received:

 
class Global.camera: Loadable 

  // A variable to store image data. 
  UVar.new(this, "val"); 
  val = 0; 
}|;  

Subscribe to the topic Now, our Publisher is running and we have a camera waiting for data. All we need to do is connecting to the Publisher with a topic, the Subscriber.


PIC

Figure 15.1: Output from rxgraph

Have a look at the different topics created by the Publisher, for instance by running rxgraph, which generates the graph in paragraph 15.1. As you can see, seven topics are available for the camera. We will use the ‘/camera/image/compressed’ topic for this example. For further information about the image format in ROS see http://www.ros.org/doc/api/sensor_msgs/html/msg/CompressedImage.html.

 
var cameraTopic = Ros.Topic.new("/camera/image/compressed")|; 
at (cameraTopic.onMessage?(var imgMsg)) 

  // Converting the ROS image to Urbi format. 
  imgMsg["data"].keywords = imgMsg["format"]| 
  // We can now store the data into camera. 
  if (!camera.val) 
    echo("Image well received. Store the image into the camera") | 
  camera.val = imgMsg["data"]; 
}, 
// Waiting for the "publisher" Process to be set up. 
sleep(2s); 
cameraTopic.subscribe;  

We are now connected and ready to display.

 
[00000003] *** Image well received. Store the image into the camera  

In a new terminal run urbi-image:

 
$ urbi-image 
Monitor created window 62914561 
***Frame rate: 5.000000 fps***  

You have now your image displayed in a window.

15.4 Image Subscriber from Urbi to ROS

Now, we want to send images to ROS using a Urbi Publisher. Make sure roscore is running and ‘learning_image_transport’ package is compiled.

Run the Subscriber The basic Subscriber in the ‘learning_image_transport’ package is expecting a ‘/camera/image’ topic. To avoid modifying the Subscriber code in ROS, we will simply ask to the Subscriber topic to accept ‘/camera/image/compressed’ topics.

 
var subscriber = 
  Process.new("rosrun"
              ["learning_image_transport""my_subscriber"
              "_image_transport:=compressed"]); 
[00037651] Process rosrun 
subscriber.run;  

Publishing images with Urbi The ‘sensor_msgs/CompressedImage’ message format provides a structure that requires a few changes.

 
// File.new("...").content returns a Binary. 
var urbiImage = File.new("test.jpg").content|; 
urbiImage.keywords = "jpeg"|; 
 
var publisher = Ros.Topic.new("/camera/image/compressed")|; 
// Advertising the type of message used. 
publisher.advertise("sensor_msgs/CompressedImage"); 
 
var rosImg = publisher.structure.new|; 
// The rosImg is a dictionary containing a Binary and a String. 
rosImg["data"] = urbiImage|; 
rosImg["format"] = "jpeg"|;  

This message contains more fields but you need only these two to send an image.

Now, you just have to publish the image.

 
// Publishing at regular intervals. 
every (500ms) 

  publisher << img; 
},  

Communication is done, the image should be displayed.

15.5 Remote communication

We have worked with a roscore running on the machine as the ROS processes but the purpose of using ROS with Urbi is to communicate with a remote machine. All you need is to setup your network configuration to avoid unexpected behaviors (see NetworkSetup2 ).

Make sure the ROS environment variables are well set, especially ROS_URI, ROS_HOSTNAME, ROS_IP.

See Tutorials/MultipleMachines3 for additional information.

Try our tutorials remotely to check if the connection is set correctly.

To go further Please see the Urbi/ROS Reference Manual, Chapter 24.

Part III
Guidelines and Cook Books

16 Installation
 16.1 Download
 16.2 Install & Check
17 Frequently Asked Questions
 17.1 Build Issues
 17.2 Troubleshooting
 17.3 urbiscript
 17.4 UObjects
 17.5 Miscellaneous
18 Urbi Guideline
 18.1 urbiscript Programming Guideline
19 Migration from urbiscript 1 to urbiscript 2
 19.1 $(Foo)
 19.2 delete Foo
 19.3 emit Foo
 19.4 eval(Foo)
 19.5 foreach
 19.6 group
 19.7 loopn
 19.8 new Foo
 19.9 self
 19.10 stop Foo
 19.11 # line
 19.12 tag+end
20 Building Urbi SDK
 20.1 Requirements
 20.2 Check out
 20.3 Bootstrap
 20.4 Configure
 20.5 Compile
 20.6 Install
 20.7 Relocatable
 20.8 Run
 20.9 Check

About This Part

This part contains guides to some specific aspects of Urbi SDK.
  Chapter 16 Installation
 
Complete instructions on how to install Urbi SDK.
  Chapter 17 Frequently Asked Questions
 
Some answers to common questions.
  Chapter 18 Urbi Guideline
 
Based on our own experience, and code that users have submitted to us, we suggest a programming guideline for Urbi SDK.
  Chapter 19 Migration from urbiscript 1 to urbiscript 2
 
This chapter is intended to people who want to migrate programs in urbiscript 1 to urbiscript 2.
  Chapter 20 Building Urbi SDK
 
Building Urbi SDK from the sources. How to install it, how to check it and so forth.

Chapter 16
Installation

 16.1 Download
 16.2 Install & Check
  16.2.1 GNU/Linux and Mac OS X
  16.2.2 Windows

16.1 Download

Various pre-compiled packages are provided. They are named

urbi-sdk-version-arch-os-compiler.ext

where

version
specifies the exact revision of Urbi that you are using. It can be simple, 2.0, or more complex, 2.0-beta3-137-g28f8880. In that case,
2.0
is the version of the Urbi Kernel,
beta3
designates the third pre-release,
137
is the number of changes since beta3 (not counting changes in sub-packages),
g28f8880
is a version control identifier, used internally to track the exact version that is being tested by our users.
arch
describes the architecture, the cpu: ARM, ppc, or x86.
os
is the operating system: linux for GNU/Linux, osx for Mac OS X, or windows for Microsoft Windows.
compiler
is the tool chain used to compile the programs: gcc4 for the GNU Compiler Collection 4.x, vcxx2005 for Microsoft Visual C++ 2005, vcxx2008 for Microsoft Visual C++ 2008.
ext
is the package format extension. For Unix architectures, tar.bz2; uncompress them with tar xf tarfile. For Windows hosts, we provide zip files (‘*.zip’) for both “release” and “debug” flavors, and installers (for instance ‘*.exe’). You are encouraged to use the installers, since in addition to installing headers and libraries, they also install Visual C++ Wizards to create UObjects, they take care of installing the Visual Runtime if needed, and they install Gostai Console and Gostai Editor.

16.2 Install & Check

The package is relocatable, i.e., it does not need to be put at a specific location, nor does it need special environment variables to be set. It is not necessary to be a super-user to install it. The root of the package, denoted by urbi-root hereafter, is the absolute name of the directory which contains the package.

After the install, the quickest way to test your installation is to run the various programs.

16.2.1 GNU/Linux and Mac OS X

Decompress the package where you want to install it. If urbi-sdk-2.x denotes the version of Urbi SDK you downloaded (say, urbi-sdk-2.x is ‘urbi-sdk-2.3-linux-x86-gcc4’), run something like:

 
$ rm -rf urbi-root 
cd /tmp 
$ tar xf path-to/urbi-sdk-2.x.tar.bz2 
$ mv urbi-sdk-2.x urbi-root  

This directory, urbi-root, should contain ‘bin’, ‘FAQ.txt’ and so forth. Do not move things around inside this directory. In order to have an easy access to the Urbi programs, set up your PATH:

 
export PATH="urbi-root/bin:$PATH"  

 
# Check that urbi is properly set up. 
$ urbi --version 
 
# Check that urbi-launch is properly installed. 
$ urbi-launch --version 
# Check that urbi-launch can find its dependencies. 
$ urbi-launch -- --version 
 
# Check that Urbi can compute. 
$ urbi -e ’1+2*3; shutdown;’ 
[00000175] 7  

16.2.2 Windows

Decompress the zip file wherever you want or execute the installer.

Execute the script ‘urbi.bat’, located at the root of the uncompressed package. It should open a terminal with an interactive Urbi session.

Cygwin Issues

Inputs and outputs of windows native application are buffered under Cygwin. Thus, either running the interactive mode of Urbi or watching the output of the server under Cygwin is not recommended.

Chapter 17
Frequently Asked Questions

 17.1 Build Issues
  17.1.1 Complaints about ‘+=
  17.1.2 error: ‘<anonymous>’ is used uninitialized in this function
  17.1.3 AM_LANGINFO_CODESET
  17.1.4 configure: error: The Java VM java failed
  17.1.5 make check’ fails
 17.2 Troubleshooting
  17.2.1 error while loading shared libraries: libport.so
  17.2.2 Error 1723: “A DLL required for this install to complete could not be run.”
  17.2.3 When executing a program, the message “The system cannot execute the specified program.” is raised.
  17.2.4 When executing a program, the message “This application has failed to start” is raised.
  17.2.5 The server dies with “stack exhaustion”
  17.2.6 ’myuobject: file not found’. What can I do?
17.2.6.1 Getting a better diagnostic
17.2.6.2 GNU/Linux
17.2.6.3 Mac OS X
17.2.6.4 Windows

 17.3 urbiscript
  17.3.1 Objects lifetime
17.3.1.1 How do I create a new Object derivative?
17.3.1.2 How do I destroy an Object?

  17.3.2 Slots and variables
17.3.2.1 Is the lobby a scope?
17.3.2.2 How do I add a new slot in an object?
17.3.2.3 How do I modify a slot of my object?
17.3.2.4 How do I create or modify a local variable?
17.3.2.5 How do I make a constructor?
17.3.2.6 How can I manipulate the list of prototypes of my objects?
17.3.2.7 How can I know the slots available for a given object?
17.3.2.8 How do I create a new function?

  17.3.3 Tags
17.3.3.1 How do I create a tag?
17.3.3.2 How do I stop a tag?
17.3.3.3 Can tagged statements return a value?

  17.3.4 Events
17.3.4.1 How do I create an event?
17.3.4.2 How do I emit an event?
17.3.4.3 How do I catch an event?

  17.3.5 Standard Library
17.3.5.1 How can I iterate over a list?

 17.4 UObjects
  17.4.1 Is the UObject API Thread-Safe?
17.4.1.1 Plugin mode
17.4.1.2 Remote mode

 17.5 Miscellaneous
  17.5.1 What has changed since the latest release?
  17.5.2 How can I contribute to the code?
  17.5.3 How do I report a bug?

17.1 Build Issues

17.1.1 Complaints about ‘+=

Although we tried to avoid it, there might still be shell scripts where we use ‘+=’, which Ash (aka, dash and sash) does not support. Please, use bash or zsh instead of Ash as /bin/sh.

17.1.2 error: ‘<anonymous>’ is used uninitialized in this function

If you encounter this error:

 
cc1plus: warnings being treated as errors 
parser/ugrammar.hh: In member function \ 
  ‘void yy::parser::yypush_(const char*, int, yy::parser::symbol_type&)’: 
parser/ugrammar.hh:1240: error: ‘<anonymous>’ is used uninitialized \ 
  in this function 
parser/ugrammar.cc:1305: note: ‘<anonymous>’ was declared here 
parser/ugrammar.hh: In member function \ 
  ‘void yy::parser::yypush_(const char*, yy::parser::stack_symbol_type&)’: 
parser/ugrammar.hh:1240: error: ‘<anonymous>’ is used uninitialized \ 
  in this function 
parser/ugrammar.cc:1475: note: ‘<anonymous>’ was declared here  

then you found a problem that we don’t know how to resolved currently. Downgrade from GCC-4.4 to GCC-4.3.

17.1.3 AM_LANGINFO_CODESET

If at bootstrap you have something like:

 
configure:12176: error: possibly undefined macro: AM_LANGINFO_CODESET 
 If this token and others are legitimate, please use m4_pattern_allow. 
 See the Autoconf documentation. 
configure:12246: error: possibly undefined macro: gl_GLIBC21  

it probably means your Automake installation is incomplete. See the Automake item in Section 20.1.

17.1.4 configure: error: The Java VM java failed

If you experience the following failure:

 
checking if java works... 
configure: error: The Java VM java failed 
                 (see config.log, check the CLASSPATH?)  

and if you looked at ‘config.log’, you should find something like:

 
Exception in thread "main" java.lang.NoClassDefFoundError: Test 
Caused by: java.lang.ClassNotFoundException: Test 
         at java.net.URLClassLoader$1.run(URLClassLoader.java:202) 
         at java.security.AccessController.doPrivileged(Native Method) 
         at java.net.URLClassLoader.findClass(URLClassLoader.java:190) 
         at java.lang.ClassLoader.loadClass(ClassLoader.java:306) 
         at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301) 
         at java.lang.ClassLoader.loadClass(ClassLoader.java:247) 
 Could not find the main class: Test.  Program will exit.  

You might be trying to compile Urbi SDK from a directory with non-ASCII characters in its full name (for instance ‘/home/jessy/Téléchargements/Sources’). In that case the JVM fails to decode properly the path, and configure fails with the above message.

Move you sources elsewhere, with only plain ASCII characters, such as ‘/home/jessy/Sources’.

17.1.5 make check’ fails

Be sure to read Section 20.9. In particular, run ‘make check’ several times (see Section 20.9 to know why). If the failures remain, please submit the ‘test-suite.log’ file(s) (see Section 17.5.3).

17.2 Troubleshooting

17.2.1 error while loading shared libraries: libport.so

If on GNU/Linux you get an error such as:

 
urbi-sdk/2.7.1 $ ./bin/urbi 
./bin/urbi: error while loading shared libraries: libport.so: \ 
      cannot open shared object file: No such file or directory  

then check that ‘/proc’ is properly mounted. To make Urbi SDK relocatable, executables and libraries use a relative path to their peers. To resolve these paths into absolute paths, the loader needs to know where the program is located, a feature provided by ‘/proc’. If for instance you run Urbi SDK in a chrooted environment, then it is possible that you forgot to mount ‘/proc’. The traditional ps utility also needs ‘/proc’ to be mounted, so running it would also help checking if the setup is complete.

17.2.2 Error 1723: “A DLL required for this install to complete could not be run.”

This error is raised when you try to install a program like vcredist-x86.exe. This program use the “Windows Installer” which is probably outdated on your system.

To fix this problem, update the “Windows Installer” and re-start the installation of vcredist which should no longer fail.

17.2.3 When executing a program, the message “The system cannot execute the specified program.” is raised.

This library is necessary to start running any application. Run ‘vcredist-x86.exe’ to install the missing libraries.

If you have used the Urbi SDK installer, it is ‘vcredist-x86.exe’ in your install directory. Otherwise download it from the Microsoft web site. Be sure to get the one corresponding to the right Visual C++ version.

17.2.4 When executing a program, the message “This application has failed to start” is raised.

Same answer as Section 17.2.3.

17.2.5 The server dies with “stack exhaustion”

Your program might be deeply recursive, or use large temporary objects. Use ‘--stack-size’ to augment the stack size, see Section 21.3.

Note that one stack is allocated per “light thread”. This can explain why programs that heavily rely on concurrency might succeed where sequential programs can fail. For instance the following program is very likely to quickly exhaust the (single) stack.

 
function consume (var num) 

  if (num) 
    consume(num - 1) | consume(num - 1) 
}|; 
consume (512);  

But if you use & instead of |, then each recursive call to consume will be spawn with a fresh stack, and therefore none will run out of stack space:

 
function consume (var num) 

  if (num) 
    consume(num - 1) & consume(num - 1) 
}|; 
consume (512);  

However your machine will run out of resources: this heavily concurrent program aims at creating no less than 2513 threads, about 2.68 × 10156 (a 156-digit long number, by far larger than the number of atoms in the observable universe, estimated to 1080).

17.2.6 ’myuobject: file not found’. What can I do?

If urbi-launch (or urbi) fails to load an UObject (a shared library or DLL) although the file exists, then the most probable cause is an undefined symbol in your shared library.

17.2.6.1Getting a better diagnostic
First, set the GD_LEVEL environment variable (see Section 21.1.2) to some high level, say DUMP, to log messages from urbi-launch. You might notice that your library is not exactly where you thought urbi-launch was looking at.

17.2.6.2GNU/Linux
A libltdl quirk prevents us from displaying a more accurate error message. You can use a tool named ltrace to obtain the exact error message. Ltrace is a standard package on most Linux distributions. Run it with ‘ltrace -C -s 1024 urbi-launch ...’, and look for lines containing ‘dlerror’ in the output. One will contain the exact message that occurred while trying to load your shared library.

It is also useful to use ldd to check that the dependencies of your object are correct. See the documentation of ldd on your machine (‘man ldd’). The following run is successful: every request (left-hand side of =>) is satisfied (by the file shown on the right-hand side).

 
$ all.so 
        linux-gate.so.1 =>  (0xb7fe8000) 
        libstdc++.so.6 => \ 
          /usr/lib/gcc/i686-pc-linux-gnu/4.4.1/libstdc++.so.6 (0xb7eba000) 
        libm.so.6 => /lib/libm.so.6 (0xb7e94000) 
        libc.so.6 => /lib/libc.so.6 (0xb7d51000) 
        libgcc_s.so.1 => \ 
          /usr/lib/gcc/i686-pc-linux-gnu/4.4.1/libgcc_s.so.1 (0xb7d35000) 
        /lib/ld-linux.so.2 (0xb7fe9000)  

The following run shows a broken dependency.

 
# A simple C++ program. 
echo ’int main() {}’ >foo.cc 
 
# Compile it, and depend on the libport shared library. 
$ g++ foo.cc -Lurbi-root/gostai/lib -lport -o foo 
 
# Run it. 
$ ./foo 
./foo: error while loading shared libraries: \ 
  libport.so: cannot open shared object file: No such file or directory 
 
# See that ldd is unhappy. 
$ ldd foo 
        linux-gate.so.1 =>  (0xb7fa4000) 
        libport.so => not found 
        libstdc++.so.6 => \ 
          /usr/lib/gcc/i686-pc-linux-gnu/4.4.1/libstdc++.so.6 (0xb7eae000) 
        libm.so.6 => /lib/libm.so.6 (0xb7e88000) 
        libgcc_s.so.1 => \ 
          /usr/lib/gcc/i686-pc-linux-gnu/4.4.1/libgcc_s.so.1 (0xb7e6c000) 
        libc.so.6 => /lib/libc.so.6 (0xb7d29000) 
        /lib/ld-linux.so.2 (0xb7fa5000)  

Notice the ‘not found’ message. The shared object could not be loaded because it is not found in the runtime path, which is the list of directories where the system looks for shared objects to be loaded when running a program.

You may extend your LD_LIBRARY_PATH to include the missing directory.

 
export LD_LIBRARY_PATH=urbi-root/gostai/lib:$LD_LIBRARY_PATH 
# Run it. 
$ ./foo  

17.2.6.3Mac OS X
Set the DYLD_PRINT_LIBRARIES environment variable to 1 to make the shared library loader report the libraries it loads on the standard error stream.

Use otool to check whether a shared object “finds” all its dependencies.

 
$ otool -L all.so 
all.so: 
        /usr/lib/libstdc++.6.dylib \ 
          (compatibility version 7.0.0, current version 7.4.0) 
        /usr/lib/libgcc_s.1.dylib \