Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proposal for simulation interfaces #1

Open
wants to merge 17 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
cmake_minimum_required(VERSION 3.8)
project(simulation_interfaces)

if(NOT CMAKE_CXX_STANDARD)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
endif()
if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
add_compile_options(-Wall -Wextra -Wpedantic)
endif()

find_package(ament_cmake REQUIRED)
find_package(builtin_interfaces REQUIRED)
find_package(geometry_msgs REQUIRED)
find_package(rosidl_default_generators REQUIRED)
find_package(std_msgs REQUIRED)

set(msg_files
"msg/Entity.msg"
"msg/EntityState.msg"
"msg/EntityWithState.msg"
"msg/NamedPose.msg"
"msg/PoseBounds.msg"
"msg/SimulatorFeatures.msg"
"msg/Spawnable.msg"
)

set(srv_files
"srv/DeleteEntity.srv"
"srv/GetEntities.srv"
"srv/GetEntityState.srv"
"srv/GetNamedPoses.srv"
"srv/GetSimulatorFeatures.srv"
"srv/GetSpawnables.srv"
"srv/ResetSimulation.srv"
"srv/SetEntityState.srv"
"srv/SetSimulationPaused.srv"
"srv/SpawnEntity.srv"
"srv/StepSimulation.srv"
)

set(action_files
"action/MultiStepSimulation.action"
)

rosidl_generate_interfaces(${PROJECT_NAME}
${msg_files}
${srv_files}
${action_files}
DEPENDENCIES builtin_interfaces std_msgs geometry_msgs
ADD_LINTER_TESTS
)

ament_export_dependencies(rosidl_default_runtime)

ament_package()
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
# simulation_interfaces
Standard interfaces for interacting with simulators from ROS 2
# Simulation Interfaces

Standard ROS 2 interfaces for interacting with simulators.
Messages, services, and actions are documented in their respective files.
11 changes: 11 additions & 0 deletions action/MultiStepSimulation.action
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Assuming the simulation is paused, simulate a finite number of steps and return to paused state.
# The action returns feedback after each complete step.
# For a service alternative, see StepSimulation, which often makes more sense when doing a single step (steps = 1).

uint64 steps # Action goal: step through the simulation loop this many times.
---
bool success # Return true if stepping is supported and was successful.
string status_message # Additional comments or error status.
adamdbrw marked this conversation as resolved.
Show resolved Hide resolved
# Calling with simulation not paused will return failure and an appropriate message.
---
uint64 completed_steps # Action feedback: number of completed steps in this action so far.
4 changes: 4 additions & 0 deletions msg/Entity.msg
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Entity information

string name # Scoped name of the entity. It must be unique (including namespace).
string description # Optional: additional information about entity.
8 changes: 8 additions & 0 deletions msg/EntityState.msg
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Entity current pose, twist and acceleration

std_msgs/Header header # Frame and timestamp for pose and twist. Empty frame defaults to world.
geometry_msgs/Pose pose # Pose in reference frame, ground truth.
geometry_msgs/Twist twist # Ground truth body twist in the reference frame.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think for ground truth twist, the body twist has to be expressed in the world frame. In the convention mentioned in ros2/common_interfaces#240, we'd have:

body_frame_id = "frame_name_of_entity" 
header.frame_id = "world"
reference_frame_id = "world"

@tfoote can you confirm? When both header.frame_id and reference_frame_id are "world", it looks like a spatial twist, but that's not what we need here. Maybe we need to clarify that the VelocityStamped message always represents body twists, but expressed in the frame specified by reference_frame_id.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@azeey @tfoote once you confirm, I would welcome a suggestion or an extra context to make sure I understand and apply this correctly

# It is observed and defined in the local coordinates system of the body.
# See https://github.com/ros2/common_interfaces/pull/240 for conventions.
geometry_msgs/Accel acceleration # Linear and angular acceleration ground truth, following the same convention.
5 changes: 5 additions & 0 deletions msg/EntityWithState.msg
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Entity with its current ground truth state. Entities are objects in the simulation such as models and links.
# Each simulator might define what an entity is in a (slightly) different way.

Entity entity # Entity name and description
adamdbrw marked this conversation as resolved.
Show resolved Hide resolved
EntityState state # Entity current state
9 changes: 9 additions & 0 deletions msg/NamedPose.msg
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# A named pose defined in the simulation for certain purposes such as spawning.

string name # Unique name.
string description # Description for the user, e.g. "near the charging station".
string[] tags # Optional tags which can be used to determine the named pose
# purpose, for example: "spawn", "parking", "navigation_goal",
# as well as fitting entity types e.g. "drone", "turtlebot3".
geometry_msgs/Pose pose # Pose relative to world, which can be used with SpawnEntity.srv.
PoseBounds bounds # Optional pose area bounds.
11 changes: 11 additions & 0 deletions msg/PoseBounds.msg
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Bounds for named poses, e.g. to avoid spawning with other object overlap, or parking in a spot that is too small.
# Named pose might be valid for a small object, but not suitable for a large one, or a differently shaped one.
# These limits are relative to named pose or entity's top link transform, following ROS rep-103 conventions.

# By default, both fields are zero vectors which means that pose is unbounded.
# Otherwise, the fields are expected to form a valid box containing the (0,0,0) point which is the position.
# For spawning with a named pose, you should check whether the entity simulation model fits within the bounds
# before calling SpawnEntity, to avoid overlaps and unstable behavior.

geometry_msgs/Vector3 upper_right # Optional: the upper right corner of the bounds box.
geometry_msgs/Vector3 lower_left # Optional: the lower left corner of the bounds box.
34 changes: 34 additions & 0 deletions msg/SimulatorFeatures.msg
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Features supported by the simulator.

uint8 SPAWNING = 0 # Supports spawn interface (SpawnEntity).
uint8 DELETING = 1 # Supports deleting entities (DeleteEntity).
uint8 NAMED_POSES = 2 # Supports predefined named poses (GetNamedPoses).
uint8 POSE_BOUNDS = 3 # Supports pose bounds (PoseBounds).
uint8 SPAWNING_RESOURCE_STRING = 4 # Supports SpawnEntity resource_string field.

uint8 ENTITY_STATE_LISTING = 10 # Supports GetEntityState interface.
uint8 ENTITY_STATE_SETTING = 11 # Supports SetEntityState interface.

uint8 SIMULATION_RESET = 20 # Supports one or more ways to reset the simulation through ResetSimulation.
uint8 SIMULATION_RESET_TIME = 21 # Supports TIME flag for resetting.
uint8 SIMULATION_RESET_STATE = 22 # Supports STATE flag for resetting.
uint8 SIMULATION_RESET_SPAWNED = 23 # Supports SPAWNED flag for resetting.

uint8 SIMULATION_PAUSE = 30 # Supports SetSimulationPaused interface
uint8 STEP_SIMULATION_SINGLE = 31 # Supports single stepping through simulation with StepSimulation interface.
uint8 STEP_SIMULATION_MULTIPLE = 32 # Supports multi-stepping through simulation, either through StepSimulation.
# service or through MultiStepSimulation action.
uint8 STEP_SIMULATION_ACTION = 33 # Supports MultiStepSimulation action interface.


uint16[] features # A list of simulation features as specified by the list above.

# A list of additional supported formats for spawning, which might be empty. Values may include
# * sdf (SDFormat)
# * urdf (Unified Robot Description Format)
# * usd (Universal Scene Description)
# * mjcf (MuJoCo's XML format)
# or whatever simulator-native formats that are supported.
string[] spawn_formats
string custom_info # Optional: extra information for the caller, which could point to
# documentation, version compatibility and other useful meta information.
5 changes: 5 additions & 0 deletions msg/Spawnable.msg
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Robot or other object which can be spawned in simulation runtime.

string uri # URI which will be accepted by SpawnEntity service.
string description # Optional description for the user, e.g. "robot X with sensors A,B,C".
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be nice to include an optional source field here to indicate if the simulator should limit itself to spawnables available locally or should include remote sources as well.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you suggest semantics of such a field in more detail?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, this field makes more sense as an input for the GetSpawnables service. I'd imagine a simulator can have multiple sources of spawnables:

  1. Local disk (other ROS packages, files placed in directories where the simulator expects, etc.)
  2. Remote (Files from a remote service, such as Fuel)

Both of these sources may have subcategorizations to limit the number spawnables returned as well the depth of searching required.

We could make the field an array of strings and let the simulator define what the values are, or we can make them enums if there is broad agreement on what the enums should be. I lean toward an array of strings.

PoseBounds spawn_bounds # Optional spawn area bounds which fully encompass this object.
28 changes: 28 additions & 0 deletions package.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?xml version="1.0"?>
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="3">
<name>simulation_interfaces</name>
<version>1.0.0</version>
<description>A package containing simulation interfaces including messages, services and actions</description>
<maintainer email="adam.dabrowski@robotec.ai">Adam Dabrowski</maintainer>
<license>Apache License 2.0</license>
<url type="repository">https://github.com/ros-simulation/simulation-interfaces</url>
<author email="adam.dabrowski@robotec.ai">Adam Dabrowski</author>

<buildtool_depend>ament_cmake</buildtool_depend>
<buildtool_depend>rosidl_default_generators</buildtool_depend>

<depend>builtin_interfaces</depend>
<depend>geometry_msgs</depend>
<depend>std_msgs</depend>

<exec_depend>rosidl_default_runtime</exec_depend>

<test_depend>ament_lint_common</test_depend>

<member_of_group>rosidl_interface_packages</member_of_group>

<export>
<build_type>ament_cmake</build_type>
</export>
</package>
8 changes: 8 additions & 0 deletions srv/DeleteEntity.srv
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Remove an entity (a robot, other object) by unique name from the simulation

string name # Unique name with a namespace, as returned by SpawnEntity or GetEntities.

---

bool success # return true if deleted successfully.
string status_message # On failure, a user-friendly error message.
12 changes: 12 additions & 0 deletions srv/GetEntities.srv
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Get objects in the scene which can be interacted, e.g. with using SetEntityState.

string filter # Optional, defaults to empty. Return entities with matching names.
adamdbrw marked this conversation as resolved.
Show resolved Hide resolved
# Entity names are matched with the filter regular expression.
# An empty filter will result in all entities being returned.
Comment on lines +3 to +5

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking at this, another cool idea could be to tag Entitys with some category label, e.g., "robot" vs. "object" vs. "furniture", etc.

This way you can not only filter by name, but also by category -- of course, every simulator interface implementer would tag their own entities with relevant categories.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like this idea but it seems to be introducing a new concept of entity tags. Which needs to be reflected in the Entity.msg and other interfaces. Perhaps this could be an extension? This sounds much like a synthetic data feature.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sea-bass what do you think? Would you like to include labels in the PR still?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be useful to label entities with categories (as you said in the Entity.msg), and then be able to retrieve them by categories.

Should it be done with this initial PR? Not necessarily, but I'd appreciate at least a separate gitissue tracking this request. I certainly use these mechanisms all the time in my simulator.


---

EntityWithState[] entities # All entities with their states, matching the filter.

bool success # Return true if successful.
string status_message # Additional comments or error status.
10 changes: 10 additions & 0 deletions srv/GetEntityState.srv
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Get state of an entity.

string name # Unique name as returned by GetEntities / SpawnEntity.

---

EntityState entity_state # Entity ground truth state.

bool success # Return true if successful.
string status_message # Additional comments or error status.
10 changes: 10 additions & 0 deletions srv/GetNamedPoses.srv
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Get predefined poses which are convenient to for spawning, navigation goals etc.
# This is an optional simulation feature: check status_message if you receive an empty poses vector,
# to determine whether this feature is not supported by your simulator, or named poses are simply not defined.

---

NamedPose[] poses # A list of predefined poses, which may be empty.

bool success # Return true if successful.
string status_message # Additional comments or error status.
6 changes: 6 additions & 0 deletions srv/GetSimulatorFeatures.srv
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Get a list of features supported by the simulator.
# Simulators adhering to the standard need to implement at least this interface.

---

adamdbrw marked this conversation as resolved.
Show resolved Hide resolved
SimulatorFeatures features
17 changes: 17 additions & 0 deletions srv/GetSpawnables.srv
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Return a list of resources which are valid as SpawnEntity uri fields (e.g. visible to or registered in simulator).
# This interface is an optional extension and might not be implemented by your simulator, check the status_message.

adamdbrw marked this conversation as resolved.
Show resolved Hide resolved
---

Spawnable[] spawnables # Spawnable objects with URI and additional information.
string[] sources # Optional field for additional sources (local or remote) to search.
# By default, each simulator has visibility of spawnables through
# some mechanisms, e.g. a set of paths, registered assets etc.
# Since the simulator cannot possibly look everywhere,
# this field allows the user to specify additional sources.
# Unrecognized values are listed as such in the status_message,
# but do not hinder success of the response.
# Sources may include subcategories and be simulator-specific.

bool success # Return true if successful.
string status_message # Additional comments or error status.
17 changes: 17 additions & 0 deletions srv/ResetSimulation.srv
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Reset the simulation to the start, including the entire scene and the simulation time.
adamdbrw marked this conversation as resolved.
Show resolved Hide resolved
adamdbrw marked this conversation as resolved.
Show resolved Hide resolved
# Objects that were dynamically spawned are de-spawned.

uint8 DEFAULT=0 # same as ALL.
uint8 TIME=1 # Reset simulation time to start.
uint8 STATE=2 # Reset state such as poses and velocities. This may include state randomization
# if such feature is available and turned on.
uint8 SPAWNED=4 # De-spawns all spawned entities.
uint8 ALL=7 # Fully resets simulation to the start, as if it was closed and launched again.

uint8 reset_scope # Scope of the reset. Note that simulators might only support some types of resets.
adamdbrw marked this conversation as resolved.
Show resolved Hide resolved
# This is a bit field which you can check for each scope e.g. reset_scope & TIME.

---

bool success # Return true if successful.
string status_message # Additional comments or error status, such as what reset types are supported.
10 changes: 10 additions & 0 deletions srv/SetEntityState.srv
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Set a state of an object, which will result in an instant change in its pose and/or twist.

string name # Unique name as returned by GetEntities or SpawnEntity.
EntityState state # New state to set immediately. The timestamp in header is ignored.
adamdbrw marked this conversation as resolved.
Show resolved Hide resolved
# Note that the acceleration field may be ignored by simulators.

---

bool success # Return true if successful.
string status_message # Additional comments or error status.
9 changes: 9 additions & 0 deletions srv/SetSimulationPaused.srv
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Pauses or unpauses the simulation
adamdbrw marked this conversation as resolved.
Show resolved Hide resolved

bool pause # If true, sets simulation state to paused, otherwise sets it to running.
# If already in target state, nothing happens but status_message informs about it.

---

bool success # Return true if pausing / resuming was successful.
string status_message # Additional comments or error status.
32 changes: 32 additions & 0 deletions srv/SpawnEntity.srv
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Spawn an entity (a robot, other object) by name or URI
adamdbrw marked this conversation as resolved.
Show resolved Hide resolved

string name # A name to give to the spawned entity.
# If empty, a name field in the uri file or resource_string will be used,
# if supported and not empty (e.g. "name" field in SDFormat, URDF).
# If the name is still empty or not unique (as determined by the simulator),
# the service returns a generated name in the entity_name response field if the
# allow_renaming field is set to true. Otherwise, the service call fails and an
# error is returned in the status_message.
bool allow_renaming # Determines whether the spawning succeeds with a non-unique name.
# If it is set to true, the user should always check entity_name response field
# and use it for any further interactions.
string uri # Resource such as SDFormat, URDF, USD or MJCF file, a native prefab, etc.
# Valid URIs can be determined by calling GetSpawnables first, and you can check
# the simulator format support by reading SimulatorFeatures spawn_formats field.
# If uri field is empty, resource_string must not be empty.
string resource_string # An entity definition file passed as a string.
# Simulators may support spawning from a file generated on the fly (e.g. XACRO).
# Check whether it is supported by your simulator through GetSimulatorFeatures.
adamdbrw marked this conversation as resolved.
Show resolved Hide resolved
# If uri field is not empty, resource_string field will be ignored.
string entity_namespace # Spawn the entity with all its interfaces under this namespace.
geometry_msgs/PoseStamped initial_pose # Initial entity pose.
# The header contains a reference frame, which defaults to global "world" frame.
# This frame must be known to the simulator, e.g. of an object spawned earlier.
# The timestamp field in the header is ignored.

---

bool success # Return true if spawned successfully.
string status_message # On failure, a user-friendly error message.
string entity_name # Spawned entity full name, guaranteed to be unique in the simulation.
# If allow_renaming is true, it may differ from the request name field.
11 changes: 11 additions & 0 deletions srv/StepSimulation.srv
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Assuming the simulation is paused, simulate a finite number of steps and return to paused state.
# The service only returns once stepping is complete, which might take considerable time.
# There is an alternative in MultiStepSimulation action, which is worth considering for a multi-step interface.

uint64 steps # Step through the simulation loop this many times.

---

bool success # Return true if stepping is supported and was successful.
string status_message # Additional comments or error status.
# Calling with simulation not paused will return failure and an appropriate message.