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

[DO NOT MERGE] Add generic systems for Drake ROS integration #2

Closed
wants to merge 87 commits into from
Closed
Show file tree
Hide file tree
Changes from 75 commits
Commits
Show all changes
87 commits
Select commit Hold shift + click to select a range
6d9d00f
Stub code builds
sloretz Nov 10, 2020
d253479
Misc fixes to get it to build (but not link) with stub example
sloretz Nov 10, 2020
96ddcfd
Fix comments on publisher system
sloretz Nov 10, 2020
8f3f925
ROS interface implementation fleshed out
sloretz Nov 10, 2020
10a347b
Possible RosInterfaceSystem impl
sloretz Nov 11, 2020
810d6f0
Possible RosSubscriberSystem impl
sloretz Nov 11, 2020
ae95a7f
Possible RosPublisherSystem implementation
sloretz Nov 11, 2020
78be681
RosPublisherSystem uses separate Serializer interface
sloretz Nov 13, 2020
9947161
RosSubscriberSystem uses separate Serializer interface
sloretz Nov 14, 2020
2965a97
Add RS-flip-flop example
sloretz Nov 14, 2020
a5bc7d9
Add get_type_support() to SerializerInterface
sloretz Nov 19, 2020
2db7ba4
Hello world pub example
sloretz Dec 2, 2020
768eff7
Fix includes for DrakeRosInterface and RosInterfaceSystem
sloretz Dec 2, 2020
21f358f
ROS Subscriber works in Python
sloretz Dec 2, 2020
26d60b2
Implement flip-flop example in Python
sloretz Dec 3, 2020
d88de33
Update README for C++ or Python example
sloretz Dec 3, 2020
0ab7e70
Try more whitespace
sloretz Dec 3, 2020
63f8e82
Bullet to numbered list
sloretz Dec 3, 2020
87d62d1
Commands to play with the example
sloretz Dec 3, 2020
5e1509d
Blank line at EOF
sloretz Dec 14, 2020
23898ae
Add linter tests
sloretz Dec 14, 2020
5ef563d
Add LICENSE file and header comments
sloretz Dec 14, 2020
2af5023
Remove unused String import
sloretz Dec 14, 2020
3c9f79e
Satisfy uncrustify
sloretz Dec 14, 2020
fb7a0b4
Satisfy cpplint
sloretz Dec 15, 2020
2dc31ce
Custom node name, node opts, and init opts
sloretz Dec 15, 2020
914f987
Add additional publish triggers
sloretz Dec 15, 2020
dffa0e8
Subscriber already unsubs on destruction
sloretz Dec 15, 2020
8513a6a
Allow setting QoS on Python systems
sloretz Dec 16, 2020
ff7497f
Expose publish triggers to Python systems
sloretz Dec 17, 2020
a4010da
Throw exception if Serialization fails
sloretz Dec 17, 2020
49054ca
Remove obsolete comment
sloretz Dec 17, 2020
4bdf9dc
NodeOptions defaults to global context
sloretz Dec 17, 2020
16f033b
Add integration test
sloretz Dec 17, 2020
52388ad
Add Python integration test
sloretz Dec 18, 2020
6866d04
Remove debug print
sloretz Dec 18, 2020
0982520
Fix bug where context wasn't being shut down
sloretz Dec 18, 2020
957b618
Add tests for DrakeRos
sloretz Dec 18, 2020
e7759ac
Do more in Python
sloretz Dec 18, 2020
f008032
WIP: Add TfBroadcaster in C++ and Python.
hidmic Apr 19, 2021
b875a68
Add missing deps to drake_ros_systems package.xml
hidmic Apr 20, 2021
14149a9
Wrap up TfBroadcater in C++ and Python.
hidmic Apr 20, 2021
fa227ff
drake_ros_systems library, bindings, and example building
hidmic Apr 20, 2021
6182d43
Tweak TfBroadcasterSystem port names
hidmic Apr 20, 2021
02821b2
WIP: Work on iiwa_manipulator demo
hidmic Apr 20, 2021
4c3e1c7
Add type conversion utilities Pose & Transform messages
hidmic Apr 21, 2021
8982f84
Tweak TfBroadcaster system
hidmic Apr 21, 2021
38b36c4
Add C++ SceneMarkersSystem.
hidmic Apr 21, 2021
d8f0806
Add C++ RvizVisualizer system to wire all up.
hidmic Apr 21, 2021
0082091
Add Python bindings for RvizVisualizer and SceneMarkersSystem
hidmic Apr 21, 2021
9d3d5cf
Update build system
hidmic Apr 21, 2021
c9f392c
Complete iiwa_manipulator example in C++ & Python.
hidmic Apr 21, 2021
483e437
Update drake_ros_systems README.md
hidmic Apr 27, 2021
1c4693e
Add RViz configuration for iiwa_manipulator example
hidmic Apr 27, 2021
101e8c7
Document drake_ros_systems package systems
hidmic Apr 27, 2021
33e4434
Drop clock system concept.
hidmic Apr 28, 2021
9764fe4
Please linters
hidmic Apr 28, 2021
2986f07
Improve TfBroadcasterSystem API
hidmic Apr 28, 2021
944029d
Add TfBroadcasterSystem tests.
hidmic Apr 28, 2021
beabc3c
Fix TfBroadcasterSystem default arguments.
hidmic May 3, 2021
3498517
Drop unnecessary semicolon in Python
hidmic May 3, 2021
c19e5c2
Please uncrustify
hidmic May 3, 2021
c70e539
Please flake8
hidmic May 3, 2021
830dacb
Unit tests for TfBroadcasterSystem passing.
hidmic May 3, 2021
1804887
Improve SceneMarkersSystem API
hidmic May 3, 2021
a650723
Improve RvizVisualizer API
hidmic May 3, 2021
68500c3
Update Python bindings
hidmic May 3, 2021
f9064f7
Add SceneMarkersSystem tests and polish the rest
hidmic May 3, 2021
76649f6
Update iiwa_manipulator examples
hidmic May 3, 2021
abb1a79
Make RvizVisualizer publish /tf by default
hidmic May 3, 2021
1e092f6
Move examples out of drake_ros_systems.
hidmic May 3, 2021
731e82b
Add drake_ros_examples package
hidmic May 3, 2021
66f4e1d
Add type conversion tests.
hidmic May 3, 2021
4bd2953
Tweak drake_ros_examples README.md
hidmic May 3, 2021
67ed30b
Add sinusoidal motion to iiwa_manipulator demos
hidmic May 4, 2021
6e6a4e9
Update maintainers in package.xml
hidmic May 7, 2021
5e711c2
Split TfBroadcasterSystem
hidmic May 11, 2021
c6005c6
Drop unnecessary DrakeRosInterface APIs.
hidmic May 11, 2021
123259c
Update SceneMarkersSystem documentation.
hidmic May 11, 2021
4fea1a4
Use source name as scene marker namespace.
hidmic May 17, 2021
b365190
Add name conventions based on SceneGraph and MultibodyPlant metadata
hidmic May 19, 2021
1f69048
Use name conventions everywhere.
hidmic May 19, 2021
0648566
Update iiwa_manipulator example
hidmic May 19, 2021
07c0906
Please uncrustify
hidmic May 19, 2021
e380501
Tweak name conventions
hidmic May 19, 2021
7e760a7
Update SceneMarkersSystem test
hidmic May 19, 2021
f01c6c3
Fix visualization_msgs/msg/Marker scales.
hidmic May 19, 2021
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
24 changes: 24 additions & 0 deletions drake_ros_examples/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
cmake_minimum_required(VERSION 3.10)
project(drake_ros_examples)

# Default to C++14
if(NOT CMAKE_CXX_STANDARD)
set(CMAKE_CXX_STANDARD 14)
endif()

if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
add_compile_options(-Wall -Wextra -Wpedantic -Werror)
endif()

find_package(ament_cmake_ros REQUIRED)
find_package(drake REQUIRED)
find_package(drake_ros_systems REQUIRED)

add_subdirectory(examples)

if(BUILD_TESTING)
find_package(ament_lint_auto REQUIRED)
ament_lint_auto_find_test_dependencies()
endif()

ament_package()
65 changes: 65 additions & 0 deletions drake_ros_examples/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# Drake ROS Examples

This is a collection of examples built around `drake_ros_systems` C++ and Python APIs.

## Building

This package has been built and tested on Ubuntu Focal with ROS Rolling, using a Drake nightly from April 2021.
It may work on other versions of ROS and Drake, but it hasn't been tested.

To build it:

1. [Install ROS Rolling](https://index.ros.org/doc/ros2/Installation/Rolling/)
1. Source your ROS installation `. /opt/ros/rolling/setup.bash`
1. [Download April-ish 2021 Drake binary](https://drake.mit.edu/from_binary.html)
1. Extract the Drake binary installation, install it's prerequisites, and [use this Python virutalenv trick](https://drake.mit.edu/python_bindings.html#inside-virtualenv).
1. Activate the drake virtual environment
1. Build it using Colcon, or using CMake directly

**Colcon**
1. Make a workspace `mkdir -p ./ws/src`
1. `cd ./ws/src`
1. Get this code `git clone https://github.com/RobotLocomotion/drake-ros.git`
1. `cd ..`
1. Build this package and its dependencies `colcon build --packages-up-to drake_ros_systems`

**CMake**
1. Get this code `git clone https://github.com/RobotLocomotion/drake-ros.git`
1. Build the [`drake_ros_systems`](../drake_ros_systems/README.md#building) package using CMake first.
1. Manually set `CMAKE_PREFIX_PATH`: `export CMAKE_PREFIX_PATH=$CMAKE_PREFIX_PATH:$(pwd)/drake-ros/drake_ros_systems/install`
1. `cd drake-ros/drake_ros_examples`
1. Make a build and install folder to avoid installing to the whole system `mkdir build install`
1. `cd build`
1. Configure the project `cmake -DCMAKE_INSTALL_PREFIX=$(pwd)/../install ..`
1. Build the project `make && make install`

## Running

* If you built with `colcon`, then source your workspace.

```
. ./ws/install/setup.bash
# Also make sure to activate drake virtual environment
```

Now you can run C++ and Python examples using `ros2 run drake_ros_examples <example-executable-or-script>`.


* If you built with plain CMake, then source the ROS workspace and set these variables.

```
. /opt/ros/rolling/setup.bash
# Also make sure to activate drake virtual environment
# CD to repository root
export LD_LIBRARY_PATH=$(pwd)/drake_ros_systems/install/lib:$LD_LIBRARY_PATH
export LD_LIBRARY_PATH=$(pwd)/drake_ros_examples/install/lib:$LD_LIBRARY_PATH
export PYTHONPATH=$(pwd)/drake_ros_systems/install/lib/$(python -c 'import sys; print(f"python{sys.version_info[0]}.{sys.version_info[1]}")')/site-packages:$PYTHONPATH
export PYTHONPATH=$(pwd)/drake_ros_examples/install/lib/$(python -c 'import sys; print(f"python{sys.version_info[0]}.{sys.version_info[1]}")')/site-packages:$PYTHONPATH
```

Now you can run C++ and Python examples from the install folder using `./drake-ros/drake_ros_examples/install/lib/drake_ros_examples/<example-executable-or-script>`.

## List of examples

- [RS flip flop](./examples/rs_flip_flop): a latch with a ROS 2 topic interface.
- [IIWA manipulator](./examples/iiwa_manipulator): an RViz visualization of a static IIWA arm.
2 changes: 2 additions & 0 deletions drake_ros_examples/examples/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
add_subdirectory(iiwa_manipulator)
add_subdirectory(rs_flip_flop)
16 changes: 16 additions & 0 deletions drake_ros_examples/examples/iiwa_manipulator/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
add_executable(iiwa_manipulator iiwa_manipulator.cpp)
target_link_libraries(iiwa_manipulator
drake::drake
drake_ros_systems::drake_ros_systems
)

install(
PROGRAMS iiwa_manipulator.py
DESTINATION lib/${PROJECT_NAME}
)

install(
TARGETS
iiwa_manipulator
DESTINATION lib/${PROJECT_NAME}
)
21 changes: 21 additions & 0 deletions drake_ros_examples/examples/iiwa_manipulator/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# IIWA Manipulator

## Overview

Both `iiwa_manipulator` and `iiwa_manipulator.py` enable RViz visualization of a static [`ManipulationStation`](https://github.com/RobotLocomotion/drake/tree/master/examples/manipulation_station) example.
They publish the following topics:

* `/tf` (all scene frames)
* `/scene_markers` (all scene geometries, including the robot model)

## How To

Run either the C++ `iiwa_manipulator` executable or the Python `iiwa_manipulator.py` script as explained [here](../../README.md#running).

Run RViz in a different terminal with your ROS installation sourced to visualize the station:

```
ros2 run rviz2 rviz2 -d iiwa_manipulator.rviz
```


118 changes: 118 additions & 0 deletions drake_ros_examples/examples/iiwa_manipulator/iiwa_manipulator.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
// Copyright 2021 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <drake/common/eigen_types.h>
#include <drake/systems/analysis/simulator.h>
#include <drake/systems/framework/diagram_builder.h>
#include <drake/systems/primitives/adder.h>
#include <drake/systems/primitives/constant_vector_source.h>
#include <drake/systems/primitives/sine.h>


#include <drake/examples/manipulation_station/manipulation_station.h>

#include <drake_ros_systems/drake_ros.hpp>
#include <drake_ros_systems/ros_interface_system.hpp>
#include <drake_ros_systems/rviz_visualizer.hpp>

#include <cmath>
#include <memory>
#include <utility>

using drake_ros_systems::DrakeRos;
using drake_ros_systems::RosInterfaceSystem;
using drake_ros_systems::RvizVisualizer;

using drake::systems::Adder;
using drake::systems::ConstantVectorSource;
using drake::systems::Sine;
using drake::systems::Simulator;
using drake::examples::manipulation_station::ManipulationStation;


int main()
{
drake::systems::DiagramBuilder<double> builder;

auto ros_interface_system =
builder.AddSystem<RosInterfaceSystem>(std::make_unique<DrakeRos>());

auto manipulation_station = builder.AddSystem<ManipulationStation>();
manipulation_station->SetupClutterClearingStation();
manipulation_station->Finalize();

// Make the base joint swing sinusoidally.
auto constant_term = builder.AddSystem<ConstantVectorSource>(
drake::VectorX<double>::Zero(manipulation_station->num_iiwa_joints()));

drake::VectorX<double> amplitudes =
drake::VectorX<double>::Zero(manipulation_station->num_iiwa_joints());
amplitudes[0] = M_PI / 4.; // == 45 degrees
const drake::VectorX<double> frequencies =
drake::VectorX<double>::Constant(manipulation_station->num_iiwa_joints(), 1.); // Hz
const drake::VectorX<double> phases =
drake::VectorX<double>::Zero(manipulation_station->num_iiwa_joints());
auto variable_term = builder.AddSystem<Sine>(amplitudes, frequencies, phases);

auto joint_trajectory_generator =
builder.AddSystem<Adder>(2, manipulation_station->num_iiwa_joints());

builder.Connect(
constant_term->get_output_port(),
joint_trajectory_generator->get_input_port(0));
builder.Connect(
variable_term->get_output_port(0),
joint_trajectory_generator->get_input_port(1));
builder.Connect(
joint_trajectory_generator->get_output_port(),
manipulation_station->GetInputPort("iiwa_position"));

auto rviz_visualizer = builder.AddSystem<RvizVisualizer>(
ros_interface_system->get_ros_interface());

builder.Connect(
manipulation_station->GetOutputPort("query_object"),
rviz_visualizer->get_graph_query_port());

auto diagram = builder.Build();
auto context = diagram->CreateDefaultContext();

auto simulator = std::make_unique<Simulator<double>>(*diagram, std::move(context));
simulator->set_target_realtime_rate(1.0);
simulator->Initialize();

auto & simulator_context = simulator->get_mutable_context();

auto & manipulation_station_context =
diagram->GetMutableSubsystemContext(*manipulation_station, &simulator_context);

auto & constant_term_context =
diagram->GetMutableSubsystemContext(*constant_term, &simulator_context);

// Fix gripper joints' position.
manipulation_station->GetInputPort("wsg_position")
.FixValue(&manipulation_station_context, 0.);

// Use default positions for every joint but the base joint.
drake::systems::BasicVector<double> & constants =
constant_term->get_mutable_source_value(&constant_term_context);
constants.set_value(
manipulation_station->GetIiwaPosition(manipulation_station_context));
constants.get_mutable_value()[0] = -M_PI / 4.;

while (true) {
simulator->AdvanceTo(simulator_context.get_time() + 0.1);
}
return 0;
}
96 changes: 96 additions & 0 deletions drake_ros_examples/examples/iiwa_manipulator/iiwa_manipulator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
#!/usr/bin/env python3
# Copyright 2021 Open Source Robotics Foundation, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import numpy as np

from drake_ros_systems import RosInterfaceSystem
from drake_ros_systems import RvizVisualizer

from pydrake.examples.manipulation_station import ManipulationStation
from pydrake.systems.analysis import Simulator
from pydrake.systems.framework import DiagramBuilder
from pydrake.systems.primitives import Adder
from pydrake.systems.primitives import ConstantVectorSource
from pydrake.systems.primitives import Sine


def main():
builder = DiagramBuilder()

ros_interface_system = builder.AddSystem(RosInterfaceSystem())

manipulation_station = builder.AddSystem(ManipulationStation())
manipulation_station.SetupClutterClearingStation()
manipulation_station.Finalize()

# Make the base joint swing sinusoidally.
constant_term = builder.AddSystem(ConstantVectorSource(
np.zeros(manipulation_station.num_iiwa_joints())))

amplitudes = np.zeros(manipulation_station.num_iiwa_joints())
amplitudes[0] = np.pi / 4. # == 45 degrees
frequencies = np.ones(manipulation_station.num_iiwa_joints())
phases = np.zeros(manipulation_station.num_iiwa_joints())
variable_term = builder.AddSystem(Sine(amplitudes, frequencies, phases))

joint_trajectory_generator = builder.AddSystem(
Adder(2, manipulation_station.num_iiwa_joints()))

builder.Connect(constant_term.get_output_port(),
joint_trajectory_generator.get_input_port(0))
builder.Connect(variable_term.get_output_port(0),
joint_trajectory_generator.get_input_port(1))
builder.Connect(joint_trajectory_generator.get_output_port(),
manipulation_station.GetInputPort('iiwa_position'))

rviz_visualizer = builder.AddSystem(
RvizVisualizer(ros_interface_system.get_ros_interface()))

builder.Connect(
manipulation_station.GetOutputPort('query_object'),
rviz_visualizer.get_graph_query_port()
)

diagram = builder.Build()

simulator = Simulator(diagram)
simulator.Initialize()
simulator.set_target_realtime_rate(1.0)
context = simulator.get_mutable_context()

manipulation_station_context = \
diagram.GetMutableSubsystemContext(manipulation_station, context)
constant_term_context = \
diagram.GetMutableSubsystemContext(constant_term, context)

# Fix gripper joints' position.
manipulation_station.GetInputPort('wsg_position').FixValue(
manipulation_station_context, np.zeros(1))

# Use default positions for every joint but the base joint.
constants = constant_term.get_mutable_source_value(constant_term_context)
constants.set_value(
manipulation_station.GetIiwaPosition(manipulation_station_context))
constants.get_mutable_value()[0] = -np.pi / 4.

try:
while True:
simulator.AdvanceTo(context.get_time() + 0.1)
except KeyboardInterrupt:
pass


if __name__ == '__main__':
main()
Loading