Logical Scene Configuration Support
The separation of logical scene and physical scene is a critical feature of the task trees framework. It can largely eliminate the need to modify the source code due to changes in the physical scene, including the environment and the robot manipulator physcial attributes.
The use of string-based logical poses (positions and rotations) also improves code readability, facilitate reusability, and eases code maintainance.
The key enabling component of the logical scene support is scene configuration file, which is a yaml file comprising definitions of logical positions and rotations in the scene, definitions of subscenes and collision objects.
Scene Configuration File
Basic Structure of a Scene Configuration File
A scene configuration file can be divided into one or more scenes. The first scene must be known as root
. The scene is the top-level identifier for refering to all the resource keys in the configuration file. Each scene defines its own reference frame and optionally an visual object attached. A scene without a specified visual object is called a frame-type scene or simply known as a frame.
The significance betwwen the root scene and the other scenes is the namespace of their configuration key-value pairs. All key-value defined under the root scene may be replaced with an empty namespace, while the variables under a subscene requires the subscene name as the namespace.
The configuration file must starts with the key scenes
, under which each scene can be added by the name as the head the scene branch. In the following example, root
is the mandatory scene, and scene_1
and scene_2
are names of custom scenes.
---
scenes:
root:
... variables of the root scene go here
named_poses:
... optional definitions of named poses
scene_1:
link:
... pose definitions of scene (which are also reference frames)
... variables of the subscene scene_1 go here
scene_2:
... variables of the subscene scene_2 go here
Specifying Configurations in the Root Scene and Other Scenes
Consider the example task_scene_4.yaml
source code below. In this example, all configuration keys are under the root scene. No subscene is defined.
---
scenes:
root:
named_poses:
home: [0.0, -0.785, 0.0, -2.36, 0.0, 1.57, 0.785] # from base
positions:
default_z: [null, null, 0.5]
area_1:
link:
parent_frame: root
type: box
model_file: null
dimensions: [0.2, 0.2, 0.01]
xyz: [0.4, 0.20, 0.00]
rpy: [0, 0, 3.14]
area_2:
link:
parent_frame: root
type: box
model_file: null
dimensions: [0.2, 0.2, 0.01]
xyz: [0.4, -0.20, 0.00]
rpy: [0, 0, 3.14]
A scene is firstly a namespace for queries and key references. It should also be the reference frame to which the poses are defined. The scene name is both the name of a reference frame and, if defined, a collision object.
The scene configuration file below defines one scene called area_1
, in which several configuration keys are defined. Note that area_1
is a reference frame (a side effect of defining a collision object). Normally, pose keys such as area_1.positions.start
and their scene (referene frame) area_1
are used together in using the move behaviours.
scenes:
area_1:
link:
parent_frame: root
type: box
model_file: null
dimensions: [0.2, 0.2, 0.01]
xyz: [0.4, 0.20, 0.00]
rpy: [0, 0, 3.14]
positions:
hover: [null, null, 0.40]
down: [null, null, 0.27]
start: [0, 0.11, null]
centre: [0, -0.015, null] # -0.01
restart: [0, -0.185, null]
end: [0, -0.06, null]
The link
Branch: Collision Objects and Custom Reference Frames
The link of a scene specifies a reference frame and optionally the collision object.
Collision object definitions comprise the following mandatory and optional keys headed by the name of the object.
type
:box
,sphere
, orobject
model_file
: the path to the mesh file if the type isobject
, which supports full file path, package relative file path, thefile
,package
andhttp
uri.dimensions
: a list of length, width, and height for abox
, the radius for asphere
, and the scaling factor as a list of 3 numbers for anobject
.xyz
: the position of the objectrpy
: the orientation of the objectparent_frame
: the reference frame for the object pose, wherenull
implies the world frame. This field is optional.
Every collision object will project its position and rotation as its own custom reference frames. The following defines the scene named area_1
which is also the name of the reference frame. In particular, the type box
indicaates that it is a collision object as well. Note that the null frame is default to the base/world frame. The pose parameter
(xyz and rpy) is the transform from area_1
to the base/world frame.
area_1:
link:
type: box
model_file: null
dimensions: [0.2, 0.2, 0.01]
xyz: [0.4, 0.20, 0.00]
rpy: [0, 0, 3.14]
frame: null
Collision objects can be defined based on the reference of another scene. If parent_frame
is not given or its value is null
, the scene becomes the default frame.
Custom reference frame definitions comprise the following mandatory and optional keys headed by the name of the frame.
type
:frame
xyz
: the position of the transformrpy
: the orientation of the transformparent_frame
orframe
: the reference frame for the custom frame, wherenull
implies the world frame. This field is optional.
Similarly, custom reference frames can be defined with another scene as the parent frame. The default frame is the root scene.
Loading and Querying the Scene Configuration File
To load the query the logical scene configuration, the task trees framework offers the class task_trees_task_scene.Scene
as an alternative. The class recognizes definitions of scene and subscenes and provides a more convenient way to query and obtain configuration values.
from task_trees.task_scene import Scene
...
self.the_scene = Scene(os.path.join(os.path.dirname(__file__), 'task_scene_4.yaml'))
The Scene
class gives every configuration key a unique reference. The reference is a dot-separated string made up of the scene namespace followed by keys of the ancestors of a key-value configuration. For example, the reference named_poses.home
refers to the home
child of the named_poses
node under the root scene (therefore the empty namespace). A configuration key under a subscene has a prepended namespace. For example, area.positions.start
refers to the value [0, 0.11, null]
in the above example.
The following code snippet demonstrates the functions key_list_under_config_key
and query_config
for listing the children keys and querying for the value of a configuration reference.
self.the_scene = Scene(os.path.join(os.path.dirname(__file__), 'task_scene.yaml'))
# setup name poses
self.named_poses = self.the_scene.key_list_under_config_key('named_poses')
for pose_name in self.named_poses:
pose_name = 'named_poses.' + pose_name
self.arm_commander.add_named_pose(pose_name, self.the_scene.query_config(pose_name))
Partial Specification of Positions and Rotations
The null
value signifies that the component is to be resolved by other specification in a compositional move target. For example the configuration positions.default_z
has the value [null, null, 0.5]
. Only the z component is specified, and the other components are omitted.
In the following compositional move target example, the missing x and y components are to be provided by the function self.generate_random_xyz
.
DoMoveXYZ('move_xy', True, arm_commander=self.arm_commander, scene=self.the_scene,
target_xyz=['positions.default_z', self.generate_random_xyz], reference_frame='area_2'),
Branches Recognized by the Task Tree Manager
The named branches of link
, and named_poses
have dedicated functions in the scene configuration.
The key
link
under a scene with thetype
equals tobox
,sphere
, andobject
is recognized by the task tree managerTaskTreesManager
class as definitions of collision objects. In the task trees, collision objects are also recognized as custom reference frames.The type of
frames
under the keylink
of a scene is recognized as definitions of custom reference frames.The key
named_poses
under the root scene is also recognized by the task tree manager as the named poses adding to the arm commander.
The TaskTreesManager
class offers the functions _define_links
, _define_frames
and _define_named_poses
for adding the scenes/collision objects, the custom reference frames, and named poses defined in the scene configuration.
Internal Logical References
Subclasses of SceneConditionalCommanderBehaviour
accepts internal references when resolving logical positions and rotations. This is handy in avoiding redundency in scene configuration.
The following part of a configuration file is extracted from task_scene.yaml
source code under /demos/pushblock
.
scenes:
root:
named_poses:
stow: [0.0, -1.244, 0.0, -2.949, 0.0, 1.704, 0.785] # from base
home: [0.0, -0.785, 0.0, -2.36, 0.0, 1.57, 0.785] # from base
regions:
workspace: [-0.5, -0.75, -0.1, 1.0, 0.5, 1.0] # min_x, min_y, min_z, max_x, max_y, max_z
inner: [-0.5, -0.75, 0.30, 0.5] # min_x, min_y, max_x, max_y
rotations:
# alpha: [3.14, null, 0.78]
# beta: [3.14, null, -0.78]
alpha: [3.14, 0, -0.785]
beta: [3.14, 0, 2.358]
push_block:
dimensions: [0.05, 0.05, 0.05]
xyz: [0.0, 0.025, 0.151]
rpy: [0, 0, 0]
...
area_1:
rotation: rotations.alpha
link:
type: box
model_file: null
dimensions: [0.1, 0.1, 0.25]
xyz: [0.4, 0.0, 0.125]
rpy: [0, 0, 1.57]
area_2:
rotation: rotations.beta
link:
type: box
model_file: null
dimensions: [0.1, 0.1, 0.25]
xyz: [0.50, -0.10, 0.125]
rpy: [0, 0, 3.14]
area_3:
rotation: rotations.beta
link:
type: box
model_file: null
dimensions: [0.1, 0.1, 0.25]
xyz: [0.6, 0.0, 0.125]
rpy: [0, 0, -1.57]
area_4:
rotation: rotations.alpha
link:
type: box
model_file: null
dimensions: [0.1, 0.1, 0.25]
xyz: [0.50, 0.10, 0.125]
rpy: [0, 0, 0]
The key rotation
of the four area scenes are mapped to either rotation.alpha
or rotation.beta
. For example, in resolving the key area_1.rotation
, if the value is a string, SceneConditionalCommanderBehaviour
attempts to resolve it once more using the scene configuration.
The internal logical reference feature improves the readability and maintainability of the configuration file.
The Scene class
The functions provided by the Scene
class are listed below.
Functions |
Remarks |
---|---|
|
The |
|
Return True if the configuration name exists |
|
Return the children keys of a configuration reference as a list |
|
Return the number of children under a list-type configuration reference |
|
Return the names of the defined scenes as a list |
|
Return the scene config branch in the config file as a dict |
|
Return the link of the scene as a LinkConfig |
|
Return the names of the defined frame-type scenes as a list |
|
Return the frame-type scene config branch in the config file as a dict |
|
Return the link of the frame as a LinkConfig |
|
Return the config of a subscene as a dict |
Refer to the API Reference for more details about these functions.
Subclassing the Scene class
Any configuration key-value pair can be queried using the Scene
class. A subclass of Scene
can be developed to add computation to the configurations.
For example, in the gridscan
demo application source code, the physical position in a grid is determined by the grid cell index and the size of grid cell. The class GridScanScene
was developed to compute the conversion of grid cell index to the corresponding physical position, based on the grid cell size specified in the scene configuration file.
Customized Configuration File
The function query_config
allows the query of any configuration key using a dot-separated query key. Each item in the query key corresponds to a node in the configuration yaml file. The item to reference a list-list structure must be a zero-starting integer. The item to reference a dict-like structure must be a string.
For example, tke query key positions.start
refers to a configuration key under the root scene.
scenes:
root:
positions:
start: [1, 2, 3]
end: [2, 3, 5]
On the other hand, the query key grid.1.rotation.alpha
matches the following structure, and it refers to the value [0, 0, 1.57]. The 1
refers to the index 1
of the list-like child under grid
.
scenes:
root:
grid:
- rotation:
alpha: [3.14, 0, 0]
- rotation:
alpha: [0, 0, 1.57]
To refer to a configuration key under a non-root scene, the query key should start with the scene name. Given the following configuration yaml file.
subscenes:
the_tank:
grid
- rotation:
alpha: [3.14, 0, 0]
- rotation:
alpha: [0, 0, 1.57]
The query key the_tank.grid.0.rotation.alpha
refers to the value [3.14, 0, 0]
.
Application developers can design a suitable configuration structure and use the function query_config
to rerieve configuration values.