[ros-ros-comm] 02/12: New upstream version 1.13.1

Jochen Sprickerhof jspricke at moszumanska.debian.org
Tue Aug 15 16:23:15 UTC 2017


This is an automated email from the git hooks/post-receive script.

jspricke pushed a commit to branch old
in repository ros-ros-comm.

commit 0a7cc73f5bf52d204ebb72746ee4ceb8211f1bf2
Author: Jochen Sprickerhof <git at jochen.sprickerhof.de>
Date:   Sun Aug 13 20:24:04 2017 +0200

    New upstream version 1.13.1
---
 clients/roscpp/CHANGELOG.rst                       |  23 ++
 clients/roscpp/CMakeLists.txt                      |   3 +-
 .../roscpp/include/boost_161_condition_variable.h  |  23 ++
 .../include/boost_161_pthread_condition_variable.h | 431 +++++++++++++++++++++
 .../boost_161_pthread_condition_variable_fwd.h     | 378 ++++++++++++++++++
 clients/roscpp/include/ros/file_log.h              |   1 +
 clients/roscpp/include/ros/forwards.h              |  18 +
 .../roscpp/include/ros/internal_timer_manager.h    |   2 +-
 clients/roscpp/include/ros/master.h                |   2 +-
 clients/roscpp/include/ros/node_handle.h           |  82 +++-
 clients/roscpp/include/ros/param.h                 |   2 +-
 clients/roscpp/include/ros/publication.h           |   2 +-
 clients/roscpp/include/ros/service_publication.h   |   2 +-
 clients/roscpp/include/ros/steady_timer.h          | 127 ++++++
 clients/roscpp/include/ros/steady_timer_options.h  |  86 ++++
 clients/roscpp/include/ros/subscription.h          |   2 +-
 clients/roscpp/include/ros/timer_manager.h         |  20 +-
 clients/roscpp/include/ros/topic_manager.h         |   2 +-
 .../roscpp/include/ros/transport_publisher_link.h  |   6 +-
 clients/roscpp/include/ros/xmlrpc_manager.h        |   2 +-
 clients/roscpp/package.xml                         |   6 +-
 clients/roscpp/src/libros/callback_queue.cpp       |  22 +-
 clients/roscpp/src/libros/connection_manager.cpp   |   2 +-
 clients/roscpp/src/libros/init.cpp                 |   2 +-
 .../roscpp/src/libros/internal_timer_manager.cpp   |  13 +-
 clients/roscpp/src/libros/master.cpp               |  10 +-
 clients/roscpp/src/libros/node_handle.cpp          |  37 +-
 clients/roscpp/src/libros/service_manager.cpp      |   2 +-
 clients/roscpp/src/libros/spinner.cpp              |  42 +-
 clients/roscpp/src/libros/steady_timer.cpp         | 224 +++++++++++
 clients/roscpp/src/libros/subscription.cpp         |  15 +-
 clients/roscpp/src/libros/this_node.cpp            |  11 +-
 clients/roscpp/src/libros/topic_manager.cpp        |   2 +-
 .../roscpp/src/libros/transport/transport_tcp.cpp  |  11 +-
 .../roscpp/src/libros/transport/transport_udp.cpp  |   4 +
 .../roscpp/src/libros/transport_publisher_link.cpp |  14 +-
 .../src/libros/transport_subscriber_link.cpp       |   2 +-
 clients/roscpp/src/libros/xmlrpc_manager.cpp       |  41 +-
 clients/rospy/CHANGELOG.rst                        |  20 +
 clients/rospy/package.xml                          |   2 +-
 clients/rospy/src/rospy/__init__.py                |   4 +
 clients/rospy/src/rospy/client.py                  |   9 +-
 clients/rospy/src/rospy/core.py                    | 105 +++--
 clients/rospy/src/rospy/impl/masterslave.py        |   9 +-
 clients/rospy/src/rospy/impl/registration.py       |   2 +
 clients/rospy/src/rospy/impl/tcpros_base.py        |  22 +-
 clients/rospy/src/rospy/impl/tcpros_service.py     |   6 +-
 clients/rospy/src/rospy/msproxy.py                 |   6 +-
 clients/rospy/src/rospy/timer.py                   |  21 +-
 clients/rospy/src/rospy/topics.py                  |  69 +++-
 ros_comm/CHANGELOG.rst                             |   9 +
 ros_comm/package.xml                               |   2 +-
 .../test_rosbag/bag_migration_tests/CMakeLists.txt |  44 ++-
 .../bag_migration_tests/MessageHistory.txt         |  54 ++-
 test/test_rosbag/bag_migration_tests/README.md     | 349 +++++++++++++++++
 test/test_rosbag/bag_migration_tests/current       |   6 -
 test/test_rosbag/bag_migration_tests/gen1          |   6 -
 test/test_rosbag/bag_migration_tests/gen2          |   6 -
 test/test_rosbag/bag_migration_tests/gen3          |   6 -
 test/test_rosbag/bag_migration_tests/generate_data |  24 --
 .../msg_current/MigratedExplicit.msg               |   4 +-
 .../msg_current/MigratedImplicit.msg               |   2 +-
 .../msg_current/MigratedMixed.msg                  |   2 +-
 .../msg_current/PartiallyMigrated.msg              |   5 +-
 .../msg_current/{Renamed4.msg => Renamed5.msg}     |   0
 .../bag_migration_tests/msg_current/Unmigrated.msg |   3 +-
 .../bag_migration_tests/msg_gen4/Constants.msg     |   3 +
 .../bag_migration_tests/msg_gen4/Converged.msg     |   2 +
 .../msg_gen4/MigratedAddSub.msg                    |   2 +
 .../{msg_current => msg_gen4}/MigratedExplicit.msg |   0
 .../{msg_current => msg_gen4}/MigratedImplicit.msg |   2 +-
 .../bag_migration_tests/msg_gen4/MigratedMixed.msg |   3 +
 .../msg_gen4/PartiallyMigrated.msg                 |   4 +
 .../{msg_current => msg_gen4}/Renamed4.msg         |   0
 .../bag_migration_tests/msg_gen4/Simple.msg        |   1 +
 .../msg_gen4/SimpleMigrated.msg                    |   1 +
 .../bag_migration_tests/msg_gen4/SubUnmigrated.msg |   2 +
 .../{msg_current => msg_gen4}/Unmigrated.msg       |   0
 .../bag_migration_tests/scripts/generate_data      |  67 ++++
 .../bag_migration_tests/scripts/generate_data_1.py |   1 -
 .../bag_migration_tests/scripts/generate_data_2.py |   1 -
 .../bag_migration_tests/scripts/generate_data_3.py |   1 -
 .../{generate_data_3.py => generate_data_4.py}     |  25 +-
 .../bag_migration_tests/scripts/generate_rules     | 154 ++++++++
 .../bag_migration_tests/test/migrate_test.py.in    |  42 +-
 .../test/migrated_explicit_rules.bmr               | 174 ++++++---
 .../test/migrated_mixed_rules.bmr                  |  33 +-
 .../test/partially_migrated_rules.bmr              |  73 ++++
 .../bag_migration_tests/test/renamed_rules.bmr     |  22 ++
 .../test/simple_migrated_rules.bmr                 |  27 +-
 test/test_rosbag/package.xml                       |   2 +-
 test/test_rosbag/test/test_bag.py                  |  10 +-
 test/test_rosbag_storage/CMakeLists.txt            |   4 +
 test/test_rosbag_storage/package.xml               |   2 +-
 .../src/create_and_iterate_bag.cpp                 | 127 +++---
 test/test_rosbag_storage/src/swap_bags.cpp         | 101 +++++
 test/test_roscpp/package.xml                       |   2 +-
 test/test_roscpp/test/launch/spinners.xml          |   4 +
 test/test_roscpp/test/src/check_master.cpp         |   2 +-
 test/test_roscpp/test/src/service_call.cpp         |  13 +
 test/test_roscpp/test/src/timer_callbacks.cpp      | 313 +++++++++++++++
 test/test_roscpp/test/test_callback_queue.cpp      |  76 ++++
 test/test_rosgraph/package.xml                     |   2 +-
 test/test_roslaunch/package.xml                    |   2 +-
 test/test_roslib_comm/package.xml                  |   2 +-
 test/test_rosmaster/package.xml                    |   2 +-
 test/test_rosparam/package.xml                     |   2 +-
 test/test_rospy/CMakeLists.txt                     |   1 +
 .../test_rospy/nodes/listener_once.py              |  55 +--
 test/test_rospy/package.xml                        |   3 +-
 .../test_rospy/test/rostest/latch_unsubscribe.test |   7 +
 .../test_rospy/test/rostest/test_basic_services.py |  17 +-
 .../test/rostest/test_latch_unsubscribe.py}        |  78 ++--
 .../test/rostest/test_rospy_client_online.py       |  51 +++
 test/test_rospy/test/unit/test_rospy_api.py        |   5 +
 test/test_rospy/test/unit/test_rospy_core.py       |   8 +-
 .../test_rospy/test/unit/test_rospy_tcpros_base.py |   4 +-
 .../test/unit/test_rospy_tcpros_pubsub.py          |   2 +-
 test/test_rospy/test/unit/test_rospy_topics.py     |   2 +-
 test/test_rosservice/package.xml                   |   2 +-
 .../test/check_rosservice_command_line_online.py   |  16 +-
 test/test_rostopic/package.xml                     |   2 +-
 tools/rosbag/CHANGELOG.rst                         |  20 +
 tools/rosbag/CMakeLists.txt                        |  16 +-
 tools/rosbag/include/rosbag/player.h               |  26 +-
 tools/rosbag/package.xml                           |   4 +-
 tools/rosbag/src/play.cpp                          |  16 +-
 tools/rosbag/src/player.cpp                        | 198 +++++++++-
 tools/rosbag/src/recorder.cpp                      |   7 +-
 tools/rosbag/src/rosbag/bag.py                     |  18 +-
 tools/rosbag/src/rosbag/migration.py               |  42 +-
 tools/rosbag/src/rosbag/rosbag_main.py             |  36 +-
 tools/rosbag/test/test_roundtrip.py                |  75 ++++
 tools/rosbag_storage/CHANGELOG.rst                 |  13 +
 tools/rosbag_storage/include/rosbag/bag.h          |   9 +
 tools/rosbag_storage/include/rosbag/buffer.h       |   7 +
 tools/rosbag_storage/include/rosbag/chunked_file.h |   8 +
 tools/rosbag_storage/include/rosbag/stream.h       |  12 +
 tools/rosbag_storage/include/rosbag/view.h         |   1 +
 tools/rosbag_storage/package.xml                   |   2 +-
 tools/rosbag_storage/rosdoc.yaml                   |   2 -
 tools/rosbag_storage/src/bag.cpp                   |  33 +-
 tools/rosbag_storage/src/buffer.cpp                |   8 +
 tools/rosbag_storage/src/chunked_file.cpp          |  35 +-
 tools/rosbag_storage/src/view.cpp                  |  13 +
 tools/rosconsole/CHANGELOG.rst                     |  11 +
 tools/rosconsole/include/ros/console.h             |   2 +-
 tools/rosconsole/package.xml                       |   2 +-
 tools/rosconsole/src/rosconsole/rosconsole.cpp     |  27 ++
 tools/rosgraph/CHANGELOG.rst                       |  12 +
 tools/rosgraph/package.xml                         |   3 +-
 tools/rosgraph/src/rosgraph/roslogging.py          |  70 +++-
 tools/rosgraph/test/test_roslogging.py             | 111 ++++++
 tools/rosgraph/test/test_roslogging_user_logger.py | 118 ++++++
 tools/roslaunch/CHANGELOG.rst                      |  18 +
 tools/roslaunch/package.xml                        |   2 +-
 tools/roslaunch/resources/example.launch           |  11 +
 tools/roslaunch/src/roslaunch/__init__.py          |  30 +-
 tools/roslaunch/src/roslaunch/core.py              |   2 +
 tools/roslaunch/src/roslaunch/depends.py           |  33 +-
 tools/roslaunch/src/roslaunch/launch.py            |  10 +-
 tools/roslaunch/src/roslaunch/loader.py            |  18 +-
 tools/roslaunch/src/roslaunch/nodeprocess.py       |   6 +
 tools/roslaunch/src/roslaunch/substitution_args.py |  46 ++-
 tools/roslaunch/src/roslaunch/xmlloader.py         |   4 +-
 .../roslaunch/test/unit/test_substitution_args.py  |   5 +-
 tools/roslaunch/test/unit/test_xmlloader.py        |  15 +
 tools/roslaunch/test/xml/test-dirname.xml          |   4 +
 tools/roslaunch/test/xml/test-dirname/included.xml |   3 +
 tools/roslaunch/test/xml/test-params-valid.xml     |   9 +
 tools/rosmaster/CHANGELOG.rst                      |  11 +
 tools/rosmaster/package.xml                        |   2 +-
 tools/rosmaster/src/rosmaster/master_api.py        |  18 +-
 tools/rosmaster/src/rosmaster/util.py              |  12 +
 tools/rosmsg/CHANGELOG.rst                         |  11 +
 tools/rosmsg/package.xml                           |   3 +-
 tools/rosmsg/src/rosmsg/__init__.py                |  19 +-
 tools/rosnode/CHANGELOG.rst                        |   9 +
 tools/rosnode/package.xml                          |   2 +-
 tools/rosout/CHANGELOG.rst                         |  12 +
 tools/rosout/package.xml                           |   2 +-
 tools/rosout/rosout.cpp                            |  61 +--
 tools/rosparam/CHANGELOG.rst                       |   9 +
 tools/rosparam/package.xml                         |   2 +-
 tools/rosservice/CHANGELOG.rst                     |   9 +
 tools/rosservice/package.xml                       |   2 +-
 tools/rostest/CHANGELOG.rst                        |  10 +
 tools/rostest/nodes/hztest                         |   2 +-
 tools/rostest/nodes/publishtest                    |  14 +-
 tools/rostest/package.xml                          |   2 +-
 tools/rostopic/CHANGELOG.rst                       |  10 +
 tools/rostopic/package.xml                         |   2 +-
 tools/rostopic/src/rostopic/__init__.py            |  14 +-
 tools/topic_tools/CHANGELOG.rst                    |   9 +
 tools/topic_tools/package.xml                      |   2 +-
 utilities/message_filters/CHANGELOG.rst            |   9 +
 utilities/message_filters/package.xml              |   2 +-
 utilities/roslz4/CHANGELOG.rst                     |  10 +
 utilities/roslz4/CMakeLists.txt                    |   3 +
 utilities/roslz4/package.xml                       |   2 +-
 utilities/roslz4/src/xxhash.h                      |  22 ++
 utilities/roswtf/CHANGELOG.rst                     |  10 +
 utilities/roswtf/package.xml                       |   4 +-
 utilities/roswtf/src/roswtf/environment.py         |   2 +-
 utilities/roswtf/src/roswtf/rosdep_db.py           |  11 +-
 .../test/check_roswtf_command_line_online.py       |  14 +-
 .../test/test_roswtf_command_line_offline.py       |   1 +
 utilities/xmlrpcpp/CHANGELOG.rst                   |  11 +
 utilities/xmlrpcpp/CMakeLists.txt                  |  20 +-
 utilities/xmlrpcpp/cmake/xmlrpcpp-extras.cmake.in  |   1 +
 utilities/xmlrpcpp/include/base64.h                | 380 ------------------
 utilities/xmlrpcpp/include/{ => xmlrpcpp}/XmlRpc.h |  12 +-
 .../xmlrpcpp/include/{ => xmlrpcpp}/XmlRpcClient.h |   6 +-
 .../xmlrpcpp/include/{ => xmlrpcpp}/XmlRpcDecl.h   |   0
 .../include/{ => xmlrpcpp}/XmlRpcDispatch.h        |   2 +-
 .../include/{ => xmlrpcpp}/XmlRpcException.h       |   2 +-
 .../xmlrpcpp/include/{ => xmlrpcpp}/XmlRpcServer.h |   6 +-
 .../{ => xmlrpcpp}/XmlRpcServerConnection.h        |   6 +-
 .../include/{ => xmlrpcpp}/XmlRpcServerMethod.h    |   2 +-
 .../xmlrpcpp/include/{ => xmlrpcpp}/XmlRpcSocket.h |   2 +-
 .../xmlrpcpp/include/{ => xmlrpcpp}/XmlRpcSource.h |   2 +-
 .../xmlrpcpp/include/{ => xmlrpcpp}/XmlRpcUtil.h   |   2 +-
 .../xmlrpcpp/include/{ => xmlrpcpp}/XmlRpcValue.h  |   2 +-
 utilities/xmlrpcpp/include/xmlrpcpp/base64.h       |   3 +
 utilities/xmlrpcpp/libb64/AUTHORS                  |  15 +
 utilities/xmlrpcpp/libb64/BENCHMARKS               |  85 ++++
 utilities/xmlrpcpp/libb64/CHANGELOG                |  33 ++
 utilities/xmlrpcpp/libb64/INSTALL                  |  44 +++
 utilities/xmlrpcpp/libb64/LICENSE                  |  29 ++
 utilities/xmlrpcpp/libb64/Makefile                 |  31 ++
 utilities/xmlrpcpp/libb64/README                   | 143 +++++++
 utilities/xmlrpcpp/libb64/TODO                     |   0
 utilities/xmlrpcpp/libb64/include/b64/cdecode.h    |  29 ++
 utilities/xmlrpcpp/libb64/include/b64/cencode.h    |  32 ++
 utilities/xmlrpcpp/libb64/include/b64/decode.h     |  72 ++++
 utilities/xmlrpcpp/libb64/include/b64/encode.h     |  79 ++++
 utilities/xmlrpcpp/libb64/src/Makefile             |  43 ++
 utilities/xmlrpcpp/libb64/src/cdecode.c            |  88 +++++
 utilities/xmlrpcpp/libb64/src/cencode.c            | 109 ++++++
 utilities/xmlrpcpp/package.xml                     |   2 +-
 utilities/xmlrpcpp/src/XmlRpcClient.cpp            |   6 +-
 utilities/xmlrpcpp/src/XmlRpcDispatch.cpp          |   6 +-
 utilities/xmlrpcpp/src/XmlRpcServer.cpp            |  12 +-
 utilities/xmlrpcpp/src/XmlRpcServerConnection.cpp  |   6 +-
 utilities/xmlrpcpp/src/XmlRpcServerMethod.cpp      |   4 +-
 utilities/xmlrpcpp/src/XmlRpcSocket.cpp            |   4 +-
 utilities/xmlrpcpp/src/XmlRpcSource.cpp            |   6 +-
 utilities/xmlrpcpp/src/XmlRpcUtil.cpp              |   4 +-
 utilities/xmlrpcpp/src/XmlRpcValue.cpp             |  79 ++--
 .../xmlrpcpp/{test => standalone-tests}/.cvsignore |   0
 .../{test => standalone-tests}/FileClient.cpp      |   2 +-
 .../{test => standalone-tests}/FileClient.dsp      |   0
 .../{test => standalone-tests}/FileClient.vcproj   |   0
 .../{test => standalone-tests}/HelloClient.cpp     |   2 +-
 .../{test => standalone-tests}/HelloClient.dsp     |   0
 .../{test => standalone-tests}/HelloClient.vcproj  |   0
 .../{test => standalone-tests}/HelloServer.cpp     |   2 +-
 .../{test => standalone-tests}/HelloServer.dsp     |   0
 .../{test => standalone-tests}/HelloServer.vcproj  |   0
 .../xmlrpcpp/{test => standalone-tests}/Makefile   |   0
 .../TestBase64Client.cpp                           |   2 +-
 .../TestBase64Client.dsp                           |   0
 .../TestBase64Client.vcproj                        |   0
 .../TestBase64Server.cpp                           |   2 +-
 .../TestBase64Server.dsp                           |   0
 .../TestBase64Server.vcproj                        |   0
 .../{test => standalone-tests}/TestValues.cpp      |   2 +-
 .../{test => standalone-tests}/TestValues.dsp      |   0
 .../{test => standalone-tests}/TestValues.vcproj   |   0
 .../{test => standalone-tests}/TestValuesWin32.cpp |   2 +-
 .../{test => standalone-tests}/TestXml.cpp         |   2 +-
 .../{test => standalone-tests}/TestXml.dsp         |   0
 .../{test => standalone-tests}/TestXml.vcproj      |   0
 .../{test => standalone-tests}/Validator.cpp       |   2 +-
 .../{test => standalone-tests}/Validator.dsp       |   0
 .../{test => standalone-tests}/Validator.vcproj    |   0
 .../arrayOfStructsTest.xml                         |   0
 .../{test => standalone-tests}/bool_test.cpp       |   2 +-
 .../countTheEntities.xml                           |   0
 .../{test => standalone-tests}/easyStructTest.xml  |   0
 .../xmlrpcpp/{test => standalone-tests}/echo.xml   |   0
 .../{test => standalone-tests}/echoStructTest.xml  |   0
 .../xmlrpcpp/{test => standalone-tests}/pngnow.png |   0
 .../port_zero_server.cpp                           |   2 +-
 utilities/xmlrpcpp/test/CMakeLists.txt             |   2 +
 utilities/xmlrpcpp/test/xmlrpcvalue_base64.cpp     | 150 +++++++
 286 files changed, 5981 insertions(+), 1155 deletions(-)

diff --git a/clients/roscpp/CHANGELOG.rst b/clients/roscpp/CHANGELOG.rst
index 8107a5d..5140755 100644
--- a/clients/roscpp/CHANGELOG.rst
+++ b/clients/roscpp/CHANGELOG.rst
@@ -2,6 +2,29 @@
 Changelog for package roscpp
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
+1.13.1 (2017-07-27)
+-------------------
+* add SteadyTimer, used in TimerManager (`#1014 <https://github.com/ros/ros_comm/issues/1014>`_)
+* include missing header for writev() (`#1105 <https://github.com/ros/ros_comm/pull/1105>`_)
+* clean the namespace to get rid of double or trailing forward slashes (`#1100 <https://github.com/ros/ros_comm/issues/1100>`_)
+* add missing mutex lock for publisher links (`#1090 <https://github.com/ros/ros_comm/pull/1090>`_)
+* fix race condition that lead to miss first message (`#1058 <https://github.com/ros/ros_comm/issues/1058>`_)
+* fix bug in transport_tcp on Windows (`#1050 <https://github.com/ros/ros_comm/issues/1050>`_)
+* add subscriber to connection log messages (`#1023 <https://github.com/ros/ros_comm/issues/1023>`_)
+* avoid deleting XmlRpcClient while being used in another thread (`#1013 <https://github.com/ros/ros_comm/issues/1013>`_)
+
+1.13.0 (2017-02-22)
+-------------------
+* remove support for multiple spinners on the same queue which existed only for backward compatibily (`#988 <https://github.com/ros/ros_comm/pull/988>`_)
+
+1.12.7 (2017-02-17)
+-------------------
+* move connection specific log message to new name roscpp_internal.connections (`#980 <https://github.com/ros/ros_comm/pull/980>`_)
+* move headers to include/xmlrpcpp (`#962 <https://github.com/ros/ros_comm/issues/962>`_)
+* fix UDP block number when EAGAIN or EWOULDBLOCK (`#957 <https://github.com/ros/ros_comm/issues/957>`_)
+* fix return code of master execute function (`#938 <https://github.com/ros/ros_comm/pull/938>`_)
+* change WallTimerEvent from class to struct (`#924 <https://github.com/ros/ros_comm/pull/924>`_)
+
 1.12.6 (2016-10-26)
 -------------------
 
diff --git a/clients/roscpp/CMakeLists.txt b/clients/roscpp/CMakeLists.txt
index 6331029..ad6ccda 100644
--- a/clients/roscpp/CMakeLists.txt
+++ b/clients/roscpp/CMakeLists.txt
@@ -22,7 +22,7 @@ list(GET roscpp_VERSION_LIST 2 roscpp_VERSION_PATCH)
 
 configure_file(${CMAKE_CURRENT_SOURCE_DIR}/include/ros/common.h.in ${CATKIN_DEVEL_PREFIX}/${CATKIN_GLOBAL_INCLUDE_DESTINATION}/ros/common.h)
 
-find_package(Boost REQUIRED COMPONENTS signals filesystem system)
+find_package(Boost REQUIRED COMPONENTS chrono filesystem signals system)
 
 include_directories(include ${CATKIN_DEVEL_PREFIX}/${CATKIN_GLOBAL_INCLUDE_DESTINATION}/ros ${catkin_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS})
 
@@ -118,6 +118,7 @@ add_library(roscpp
   src/libros/poll_set.cpp
   src/libros/service.cpp
   src/libros/this_node.cpp
+  src/libros/steady_timer.cpp
   )
 
 add_dependencies(roscpp ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
diff --git a/clients/roscpp/include/boost_161_condition_variable.h b/clients/roscpp/include/boost_161_condition_variable.h
new file mode 100644
index 0000000..ee2ff46
--- /dev/null
+++ b/clients/roscpp/include/boost_161_condition_variable.h
@@ -0,0 +1,23 @@
+#ifndef BOOST_THREAD_CONDITION_VARIABLE_HPP
+#define BOOST_THREAD_CONDITION_VARIABLE_HPP
+
+//  condition_variable.hpp
+//
+//  (C) Copyright 2007 Anthony Williams
+//
+//  Distributed under the Boost Software License, Version 1.0. (See
+//  accompanying file LICENSE_1_0.txt or copy at
+//  http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/thread/detail/platform.hpp>
+#if defined(BOOST_THREAD_PLATFORM_WIN32)
+#include <boost/thread/win32/condition_variable.hpp>
+#elif defined(BOOST_THREAD_PLATFORM_PTHREAD)
+//#include <boost/thread/pthread/condition_variable.hpp>
+#include "boost_161_pthread_condition_variable.h"
+#else
+#error "Boost threads unavailable on this platform"
+#endif
+
+#endif
+
diff --git a/clients/roscpp/include/boost_161_pthread_condition_variable.h b/clients/roscpp/include/boost_161_pthread_condition_variable.h
new file mode 100644
index 0000000..8100447
--- /dev/null
+++ b/clients/roscpp/include/boost_161_pthread_condition_variable.h
@@ -0,0 +1,431 @@
+#ifndef BOOST_THREAD_CONDITION_VARIABLE_PTHREAD_HPP
+#define BOOST_THREAD_CONDITION_VARIABLE_PTHREAD_HPP
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+// (C) Copyright 2007-10 Anthony Williams
+// (C) Copyright 2011-2012 Vicente J. Botet Escriba
+
+// make sure we include our backported version first!!
+// (before the system version might be included via some of the other header files)
+#include "boost_161_pthread_condition_variable_fwd.h"
+
+#include <boost/thread/pthread/timespec.hpp>
+#include <boost/thread/pthread/pthread_mutex_scoped_lock.hpp>
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+#include <boost/thread/pthread/thread_data.hpp>
+#endif
+//#include <boost/thread/pthread/condition_variable_fwd.hpp>
+#ifdef BOOST_THREAD_USES_CHRONO
+#include <boost/chrono/system_clocks.hpp>
+#include <boost/chrono/ceil.hpp>
+#endif
+#include <boost/thread/detail/delete.hpp>
+
+#include <boost/config/abi_prefix.hpp>
+
+namespace boost
+{
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+    namespace this_thread
+    {
+        void BOOST_THREAD_DECL interruption_point();
+    }
+#endif
+
+    namespace thread_cv_detail
+    {
+        template<typename MutexType>
+        struct lock_on_exit
+        {
+            MutexType* m;
+
+            lock_on_exit():
+                m(0)
+            {}
+
+            void activate(MutexType& m_)
+            {
+                m_.unlock();
+                m=&m_;
+            }
+            ~lock_on_exit()
+            {
+                if(m)
+                {
+                    m->lock();
+                }
+           }
+        };
+    }
+
+    inline void condition_variable::wait(unique_lock<mutex>& m)
+    {
+#if defined BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED
+        if(! m.owns_lock())
+        {
+            boost::throw_exception(condition_error(-1, "boost::condition_variable::wait() failed precondition mutex not owned"));
+        }
+#endif
+        int res=0;
+        {
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+            thread_cv_detail::lock_on_exit<unique_lock<mutex> > guard;
+            detail::interruption_checker check_for_interruption(&internal_mutex,&cond);
+            pthread_mutex_t* the_mutex = &internal_mutex;
+            guard.activate(m);
+#else
+            pthread_mutex_t* the_mutex = m.mutex()->native_handle();
+#endif
+            res = pthread_cond_wait(&cond,the_mutex);
+        }
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+        this_thread::interruption_point();
+#endif
+        if(res && res != EINTR)
+        {
+            boost::throw_exception(condition_error(res, "boost::condition_variable::wait failed in pthread_cond_wait"));
+        }
+    }
+
+    inline bool condition_variable::do_wait_until(
+                unique_lock<mutex>& m,
+                struct timespec const &timeout)
+    {
+#if defined BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED
+        if (!m.owns_lock())
+        {
+            boost::throw_exception(condition_error(EPERM, "boost::condition_variable::do_wait_until() failed precondition mutex not owned"));
+        }
+#endif
+        int cond_res;
+        {
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+            thread_cv_detail::lock_on_exit<unique_lock<mutex> > guard;
+            detail::interruption_checker check_for_interruption(&internal_mutex,&cond);
+            pthread_mutex_t* the_mutex = &internal_mutex;
+            guard.activate(m);
+#else
+            pthread_mutex_t* the_mutex = m.mutex()->native_handle();
+#endif
+            cond_res=pthread_cond_timedwait(&cond,the_mutex,&timeout);
+        }
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+        this_thread::interruption_point();
+#endif
+        if(cond_res==ETIMEDOUT)
+        {
+            return false;
+        }
+        if(cond_res)
+        {
+            boost::throw_exception(condition_error(cond_res, "boost::condition_variable::do_wait_until failed in pthread_cond_timedwait"));
+        }
+        return true;
+    }
+
+    inline void condition_variable::notify_one() BOOST_NOEXCEPT
+    {
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+        boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex);
+#endif
+        BOOST_VERIFY(!pthread_cond_signal(&cond));
+    }
+
+    inline void condition_variable::notify_all() BOOST_NOEXCEPT
+    {
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+        boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex);
+#endif
+        BOOST_VERIFY(!pthread_cond_broadcast(&cond));
+    }
+
+    class condition_variable_any
+    {
+        pthread_mutex_t internal_mutex;
+        pthread_cond_t cond;
+
+    public:
+        BOOST_THREAD_NO_COPYABLE(condition_variable_any)
+        condition_variable_any()
+        {
+            int const res=pthread_mutex_init(&internal_mutex,NULL);
+            if(res)
+            {
+                boost::throw_exception(thread_resource_error(res, "boost::condition_variable_any::condition_variable_any() failed in pthread_mutex_init"));
+            }
+            int const res2 = detail::monotonic_pthread_cond_init(cond);
+            if(res2)
+            {
+                BOOST_VERIFY(!pthread_mutex_destroy(&internal_mutex));
+                boost::throw_exception(thread_resource_error(res2, "boost::condition_variable_any::condition_variable_any() failed in detail::monotonic_pthread_cond_init"));
+            }
+        }
+        ~condition_variable_any()
+        {
+            BOOST_VERIFY(!pthread_mutex_destroy(&internal_mutex));
+            BOOST_VERIFY(!pthread_cond_destroy(&cond));
+        }
+
+        template<typename lock_type>
+        void wait(lock_type& m)
+        {
+            int res=0;
+            {
+                thread_cv_detail::lock_on_exit<lock_type> guard;
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+                detail::interruption_checker check_for_interruption(&internal_mutex,&cond);
+#else
+                boost::pthread::pthread_mutex_scoped_lock check_for_interruption(&internal_mutex);
+#endif
+                guard.activate(m);
+                res=pthread_cond_wait(&cond,&internal_mutex);
+            }
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+            this_thread::interruption_point();
+#endif
+            if(res)
+            {
+                boost::throw_exception(condition_error(res, "boost::condition_variable_any::wait() failed in pthread_cond_wait"));
+            }
+        }
+
+        template<typename lock_type,typename predicate_type>
+        void wait(lock_type& m,predicate_type pred)
+        {
+            while(!pred()) wait(m);
+        }
+
+#if defined BOOST_THREAD_USES_DATETIME
+        template<typename lock_type>
+        bool timed_wait(lock_type& m,boost::system_time const& abs_time)
+        {
+            struct timespec const timeout=detail::to_timespec(abs_time);
+            return do_wait_until(m, timeout);
+        }
+        template<typename lock_type>
+        bool timed_wait(lock_type& m,xtime const& abs_time)
+        {
+            return timed_wait(m,system_time(abs_time));
+        }
+
+        template<typename lock_type,typename duration_type>
+        bool timed_wait(lock_type& m,duration_type const& wait_duration)
+        {
+            return timed_wait(m,get_system_time()+wait_duration);
+        }
+
+        template<typename lock_type,typename predicate_type>
+        bool timed_wait(lock_type& m,boost::system_time const& abs_time, predicate_type pred)
+        {
+            while (!pred())
+            {
+                if(!timed_wait(m, abs_time))
+                    return pred();
+            }
+            return true;
+        }
+
+        template<typename lock_type,typename predicate_type>
+        bool timed_wait(lock_type& m,xtime const& abs_time, predicate_type pred)
+        {
+            return timed_wait(m,system_time(abs_time),pred);
+        }
+
+        template<typename lock_type,typename duration_type,typename predicate_type>
+        bool timed_wait(lock_type& m,duration_type const& wait_duration,predicate_type pred)
+        {
+            return timed_wait(m,get_system_time()+wait_duration,pred);
+        }
+#endif
+#ifndef BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
+
+#ifdef BOOST_THREAD_USES_CHRONO
+        template <class lock_type,class Duration>
+        cv_status
+        wait_until(
+                lock_type& lock,
+                const chrono::time_point<chrono::system_clock, Duration>& t)
+        {
+          using namespace chrono;
+          typedef time_point<system_clock, nanoseconds> nano_sys_tmpt;
+          wait_until(lock,
+                        nano_sys_tmpt(ceil<nanoseconds>(t.time_since_epoch())));
+          return system_clock::now() < t ? cv_status::no_timeout :
+                                             cv_status::timeout;
+        }
+
+        template <class lock_type, class Clock, class Duration>
+        cv_status
+        wait_until(
+                lock_type& lock,
+                const chrono::time_point<Clock, Duration>& t)
+        {
+          using namespace chrono;
+          system_clock::time_point     s_now = system_clock::now();
+          typename Clock::time_point  c_now = Clock::now();
+          wait_until(lock, s_now + ceil<nanoseconds>(t - c_now));
+          return Clock::now() < t ? cv_status::no_timeout : cv_status::timeout;
+        }
+
+        template <class lock_type, class Rep, class Period>
+        cv_status
+        wait_for(
+                lock_type& lock,
+                const chrono::duration<Rep, Period>& d)
+        {
+          using namespace chrono;
+          system_clock::time_point s_now = system_clock::now();
+          steady_clock::time_point c_now = steady_clock::now();
+          wait_until(lock, s_now + ceil<nanoseconds>(d));
+          return steady_clock::now() - c_now < d ? cv_status::no_timeout :
+                                                   cv_status::timeout;
+
+        }
+
+        template <class lock_type>
+        cv_status wait_until(
+            lock_type& lk,
+            chrono::time_point<chrono::system_clock, chrono::nanoseconds> tp)
+        {
+            using namespace chrono;
+            nanoseconds d = tp.time_since_epoch();
+            timespec ts = boost::detail::to_timespec(d);
+            if (do_wait_until(lk, ts)) return cv_status::no_timeout;
+            else return cv_status::timeout;
+        }
+#endif
+#else // defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
+#ifdef BOOST_THREAD_USES_CHRONO
+
+        template <class lock_type, class Duration>
+        cv_status
+        wait_until(
+            lock_type& lock,
+            const chrono::time_point<chrono::steady_clock, Duration>& t)
+        {
+            using namespace chrono;
+            typedef time_point<steady_clock, nanoseconds> nano_sys_tmpt;
+            wait_until(lock,
+                        nano_sys_tmpt(ceil<nanoseconds>(t.time_since_epoch())));
+            return steady_clock::now() < t ? cv_status::no_timeout :
+                                             cv_status::timeout;
+        }
+
+        template <class lock_type, class Clock, class Duration>
+        cv_status
+        wait_until(
+            lock_type& lock,
+            const chrono::time_point<Clock, Duration>& t)
+        {
+            using namespace chrono;
+            steady_clock::time_point     s_now = steady_clock::now();
+            typename Clock::time_point  c_now = Clock::now();
+            wait_until(lock, s_now + ceil<nanoseconds>(t - c_now));
+            return Clock::now() < t ? cv_status::no_timeout : cv_status::timeout;
+        }
+
+        template <class lock_type, class Rep, class Period>
+        cv_status
+        wait_for(
+            lock_type& lock,
+            const chrono::duration<Rep, Period>& d)
+        {
+            using namespace chrono;
+            steady_clock::time_point c_now = steady_clock::now();
+            wait_until(lock, c_now + ceil<nanoseconds>(d));
+            return steady_clock::now() - c_now < d ? cv_status::no_timeout :
+                                                   cv_status::timeout;
+        }
+
+        template <class lock_type>
+        inline cv_status wait_until(
+            lock_type& lock,
+            chrono::time_point<chrono::steady_clock, chrono::nanoseconds> tp)
+        {
+            using namespace chrono;
+            nanoseconds d = tp.time_since_epoch();
+            timespec ts = boost::detail::to_timespec(d);
+            if (do_wait_until(lock, ts)) return cv_status::no_timeout;
+            else return cv_status::timeout;
+        }
+
+#endif
+#endif // defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
+
+#ifdef BOOST_THREAD_USES_CHRONO
+        template <class lock_type, class Clock, class Duration, class Predicate>
+        bool
+        wait_until(
+                lock_type& lock,
+                const chrono::time_point<Clock, Duration>& t,
+                Predicate pred)
+        {
+            while (!pred())
+            {
+                if (wait_until(lock, t) == cv_status::timeout)
+                    return pred();
+            }
+            return true;
+        }
+
+        template <class lock_type, class Rep, class Period, class Predicate>
+        bool
+        wait_for(
+                lock_type& lock,
+                const chrono::duration<Rep, Period>& d,
+                Predicate pred)
+        {
+          return wait_until(lock, chrono::steady_clock::now() + d, boost::move(pred));
+        }
+#endif
+
+        void notify_one() BOOST_NOEXCEPT
+        {
+            boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex);
+            BOOST_VERIFY(!pthread_cond_signal(&cond));
+        }
+
+        void notify_all() BOOST_NOEXCEPT
+        {
+            boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex);
+            BOOST_VERIFY(!pthread_cond_broadcast(&cond));
+        }
+    private: // used by boost::thread::try_join_until
+
+        template <class lock_type>
+        bool do_wait_until(
+          lock_type& m,
+          struct timespec const &timeout)
+        {
+          int res=0;
+          {
+              thread_cv_detail::lock_on_exit<lock_type> guard;
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+              detail::interruption_checker check_for_interruption(&internal_mutex,&cond);
+#else
+              boost::pthread::pthread_mutex_scoped_lock check_for_interruption(&internal_mutex);
+#endif
+              guard.activate(m);
+              res=pthread_cond_timedwait(&cond,&internal_mutex,&timeout);
+          }
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+          this_thread::interruption_point();
+#endif
+          if(res==ETIMEDOUT)
+          {
+              return false;
+          }
+          if(res)
+          {
+              boost::throw_exception(condition_error(res, "boost::condition_variable_any::do_wait_until() failed in pthread_cond_timedwait"));
+          }
+          return true;
+        }
+    };
+
+}
+
+#include <boost/config/abi_suffix.hpp>
+
+#endif
diff --git a/clients/roscpp/include/boost_161_pthread_condition_variable_fwd.h b/clients/roscpp/include/boost_161_pthread_condition_variable_fwd.h
new file mode 100644
index 0000000..2e4e4c6
--- /dev/null
+++ b/clients/roscpp/include/boost_161_pthread_condition_variable_fwd.h
@@ -0,0 +1,378 @@
+#ifndef BOOST_THREAD_PTHREAD_CONDITION_VARIABLE_FWD_HPP
+#define BOOST_THREAD_PTHREAD_CONDITION_VARIABLE_FWD_HPP
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+// (C) Copyright 2007-8 Anthony Williams
+// (C) Copyright 2011-2012 Vicente J. Botet Escriba
+
+// define to check if this backported version was included
+#define USING_BACKPORTED_BOOST_CONDITION_VARIABLE 1
+
+#include <boost/assert.hpp>
+#include <boost/throw_exception.hpp>
+#include <pthread.h>
+#include <boost/thread/cv_status.hpp>
+#include <boost/thread/mutex.hpp>
+#include <boost/thread/lock_types.hpp>
+#include <boost/thread/thread_time.hpp>
+#include <boost/thread/pthread/timespec.hpp>
+#if defined BOOST_THREAD_USES_DATETIME
+#include <boost/thread/xtime.hpp>
+#endif
+
+#ifdef BOOST_THREAD_USES_CHRONO
+#include <boost/chrono/system_clocks.hpp>
+#include <boost/chrono/ceil.hpp>
+#endif
+#include <boost/thread/detail/delete.hpp>
+#include <boost/date_time/posix_time/posix_time_duration.hpp>
+
+#include <boost/config/abi_prefix.hpp>
+
+namespace boost
+{
+  namespace detail {
+    inline int monotonic_pthread_cond_init(pthread_cond_t& cond) {
+
+#ifdef BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
+            pthread_condattr_t attr;
+            int res = pthread_condattr_init(&attr);
+            if (res)
+            {
+              return res;
+            }
+            pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
+            res=pthread_cond_init(&cond,&attr);
+            pthread_condattr_destroy(&attr);
+            return res;
+#else
+            return pthread_cond_init(&cond,NULL);
+#endif
+
+    }
+  }
+
+    class condition_variable
+    {
+    private:
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+        pthread_mutex_t internal_mutex;
+#endif
+        pthread_cond_t cond;
+
+    public:
+    //private: // used by boost::thread::try_join_until
+
+        inline bool do_wait_until(
+            unique_lock<mutex>& lock,
+            struct timespec const &timeout);
+
+        bool do_wait_for(
+            unique_lock<mutex>& lock,
+            struct timespec const &timeout)
+        {
+#if ! defined BOOST_THREAD_USEFIXES_TIMESPEC
+            return do_wait_until(lock, boost::detail::timespec_plus(timeout, boost::detail::timespec_now()));
+#elif ! defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
+            //using namespace chrono;
+            //nanoseconds ns = chrono::system_clock::now().time_since_epoch();
+
+            struct timespec ts = boost::detail::timespec_now_realtime();
+            //ts.tv_sec = static_cast<long>(chrono::duration_cast<chrono::seconds>(ns).count());
+            //ts.tv_nsec = static_cast<long>((ns - chrono::duration_cast<chrono::seconds>(ns)).count());
+            return do_wait_until(lock, boost::detail::timespec_plus(timeout, ts));
+#else
+            // old behavior was fine for monotonic
+            return do_wait_until(lock, boost::detail::timespec_plus(timeout, boost::detail::timespec_now_realtime()));
+#endif
+        }
+
+    public:
+      BOOST_THREAD_NO_COPYABLE(condition_variable)
+        condition_variable()
+        {
+            int res;
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+            res=pthread_mutex_init(&internal_mutex,NULL);
+            if(res)
+            {
+                boost::throw_exception(thread_resource_error(res, "boost::condition_variable::condition_variable() constructor failed in pthread_mutex_init"));
+            }
+#endif
+            res = detail::monotonic_pthread_cond_init(cond);
+            if (res)
+            {
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+                BOOST_VERIFY(!pthread_mutex_destroy(&internal_mutex));
+#endif
+                boost::throw_exception(thread_resource_error(res, "boost::condition_variable::condition_variable() constructor failed in detail::monotonic_pthread_cond_init"));
+            }
+        }
+        ~condition_variable()
+        {
+            int ret;
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+            do {
+              ret = pthread_mutex_destroy(&internal_mutex);
+            } while (ret == EINTR);
+            BOOST_ASSERT(!ret);
+#endif
+            do {
+              ret = pthread_cond_destroy(&cond);
+            } while (ret == EINTR);
+            BOOST_ASSERT(!ret);
+        }
+
+        void wait(unique_lock<mutex>& m);
+
+        template<typename predicate_type>
+        void wait(unique_lock<mutex>& m,predicate_type pred)
+        {
+            while(!pred()) wait(m);
+        }
+
+#if defined BOOST_THREAD_USES_DATETIME
+        inline bool timed_wait(
+            unique_lock<mutex>& m,
+            boost::system_time const& abs_time)
+        {
+#if defined BOOST_THREAD_WAIT_BUG
+            struct timespec const timeout=detail::to_timespec(abs_time + BOOST_THREAD_WAIT_BUG);
+            return do_wait_until(m, timeout);
+#else
+            struct timespec const timeout=detail::to_timespec(abs_time);
+            return do_wait_until(m, timeout);
+#endif
+        }
+        bool timed_wait(
+            unique_lock<mutex>& m,
+            xtime const& abs_time)
+        {
+            return timed_wait(m,system_time(abs_time));
+        }
+
+        template<typename duration_type>
+        bool timed_wait(
+            unique_lock<mutex>& m,
+            duration_type const& wait_duration)
+        {
+            if (wait_duration.is_pos_infinity())
+            {
+                wait(m); // or do_wait(m,detail::timeout::sentinel());
+                return true;
+            }
+            if (wait_duration.is_special())
+            {
+                return true;
+            }
+            return timed_wait(m,get_system_time()+wait_duration);
+        }
+
+        template<typename predicate_type>
+        bool timed_wait(
+            unique_lock<mutex>& m,
+            boost::system_time const& abs_time,predicate_type pred)
+        {
+            while (!pred())
+            {
+                if(!timed_wait(m, abs_time))
+                    return pred();
+            }
+            return true;
+        }
+
+        template<typename predicate_type>
+        bool timed_wait(
+            unique_lock<mutex>& m,
+            xtime const& abs_time,predicate_type pred)
+        {
+            return timed_wait(m,system_time(abs_time),pred);
+        }
+
+        template<typename duration_type,typename predicate_type>
+        bool timed_wait(
+            unique_lock<mutex>& m,
+            duration_type const& wait_duration,predicate_type pred)
+        {
+            if (wait_duration.is_pos_infinity())
+            {
+                while (!pred())
+                {
+                  wait(m); // or do_wait(m,detail::timeout::sentinel());
+                }
+                return true;
+            }
+            if (wait_duration.is_special())
+            {
+                return pred();
+            }
+            return timed_wait(m,get_system_time()+wait_duration,pred);
+        }
+#endif
+
+#ifndef BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
+
+#ifdef BOOST_THREAD_USES_CHRONO
+
+        template <class Duration>
+        cv_status
+        wait_until(
+                unique_lock<mutex>& lock,
+                const chrono::time_point<chrono::system_clock, Duration>& t)
+        {
+          using namespace chrono;
+          typedef time_point<system_clock, nanoseconds> nano_sys_tmpt;
+          wait_until(lock,
+                        nano_sys_tmpt(ceil<nanoseconds>(t.time_since_epoch())));
+          return system_clock::now() < t ? cv_status::no_timeout :
+                                             cv_status::timeout;
+        }
+
+        template <class Clock, class Duration>
+        cv_status
+        wait_until(
+                unique_lock<mutex>& lock,
+                const chrono::time_point<Clock, Duration>& t)
+        {
+          using namespace chrono;
+          system_clock::time_point     s_now = system_clock::now();
+          typename Clock::time_point  c_now = Clock::now();
+          wait_until(lock, s_now + ceil<nanoseconds>(t - c_now));
+          return Clock::now() < t ? cv_status::no_timeout : cv_status::timeout;
+        }
+
+
+
+        template <class Rep, class Period>
+        cv_status
+        wait_for(
+                unique_lock<mutex>& lock,
+                const chrono::duration<Rep, Period>& d)
+        {
+          using namespace chrono;
+          system_clock::time_point s_now = system_clock::now();
+          steady_clock::time_point c_now = steady_clock::now();
+          wait_until(lock, s_now + ceil<nanoseconds>(d));
+          return steady_clock::now() - c_now < d ? cv_status::no_timeout :
+                                                   cv_status::timeout;
+
+        }
+
+        inline cv_status wait_until(
+            unique_lock<mutex>& lk,
+            chrono::time_point<chrono::system_clock, chrono::nanoseconds> tp)
+        {
+            using namespace chrono;
+            nanoseconds d = tp.time_since_epoch();
+            timespec ts = boost::detail::to_timespec(d);
+            if (do_wait_until(lk, ts)) return cv_status::no_timeout;
+            else return cv_status::timeout;
+        }
+#endif
+
+#else // defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
+#ifdef BOOST_THREAD_USES_CHRONO
+
+        template <class Duration>
+        cv_status
+        wait_until(
+              unique_lock<mutex>& lock,
+              const chrono::time_point<chrono::steady_clock, Duration>& t)
+        {
+            using namespace chrono;
+            typedef time_point<steady_clock, nanoseconds> nano_sys_tmpt;
+            wait_until(lock,
+                        nano_sys_tmpt(ceil<nanoseconds>(t.time_since_epoch())));
+            return steady_clock::now() < t ? cv_status::no_timeout :
+                                             cv_status::timeout;
+        }
+
+        template <class Clock, class Duration>
+        cv_status
+        wait_until(
+            unique_lock<mutex>& lock,
+            const chrono::time_point<Clock, Duration>& t)
+        {
+            using namespace chrono;
+            steady_clock::time_point     s_now = steady_clock::now();
+            typename Clock::time_point  c_now = Clock::now();
+            wait_until(lock, s_now + ceil<nanoseconds>(t - c_now));
+            return Clock::now() < t ? cv_status::no_timeout : cv_status::timeout;
+        }
+
+        template <class Rep, class Period>
+        cv_status
+        wait_for(
+            unique_lock<mutex>& lock,
+            const chrono::duration<Rep, Period>& d)
+        {
+            using namespace chrono;
+            steady_clock::time_point c_now = steady_clock::now();
+            wait_until(lock, c_now + ceil<nanoseconds>(d));
+            return steady_clock::now() - c_now < d ? cv_status::no_timeout :
+                                                   cv_status::timeout;
+        }
+
+        inline cv_status wait_until(
+            unique_lock<mutex>& lk,
+            chrono::time_point<chrono::steady_clock, chrono::nanoseconds> tp)
+        {
+            using namespace chrono;
+            nanoseconds d = tp.time_since_epoch();
+            timespec ts = boost::detail::to_timespec(d);
+            if (do_wait_until(lk, ts)) return cv_status::no_timeout;
+            else return cv_status::timeout;
+        }
+#endif
+
+#endif // defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
+
+#ifdef BOOST_THREAD_USES_CHRONO
+        template <class Clock, class Duration, class Predicate>
+        bool
+        wait_until(
+                unique_lock<mutex>& lock,
+                const chrono::time_point<Clock, Duration>& t,
+                Predicate pred)
+        {
+            while (!pred())
+            {
+                if (wait_until(lock, t) == cv_status::timeout)
+                    return pred();
+            }
+            return true;
+        }
+
+        template <class Rep, class Period, class Predicate>
+        bool
+        wait_for(
+                unique_lock<mutex>& lock,
+                const chrono::duration<Rep, Period>& d,
+                Predicate pred)
+        {
+          return wait_until(lock, chrono::steady_clock::now() + d, boost::move(pred));
+        }
+#endif
+
+#define BOOST_THREAD_DEFINES_CONDITION_VARIABLE_NATIVE_HANDLE
+        typedef pthread_cond_t* native_handle_type;
+        native_handle_type native_handle()
+        {
+            return &cond;
+        }
+
+        void notify_one() BOOST_NOEXCEPT;
+        void notify_all() BOOST_NOEXCEPT;
+
+
+    };
+
+    BOOST_THREAD_DECL void notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk);
+
+}
+
+
+#include <boost/config/abi_suffix.hpp>
+
+#endif
diff --git a/clients/roscpp/include/ros/file_log.h b/clients/roscpp/include/ros/file_log.h
index 933d942..1d046d9 100644
--- a/clients/roscpp/include/ros/file_log.h
+++ b/clients/roscpp/include/ros/file_log.h
@@ -33,6 +33,7 @@
 #include "common.h"
 
 #define ROSCPP_LOG_DEBUG(...) ROS_DEBUG_NAMED("roscpp_internal", __VA_ARGS__)
+#define ROSCPP_CONN_LOG_DEBUG(...) ROS_DEBUG_NAMED("roscpp_internal.connections", __VA_ARGS__)
 
 namespace ros
 {
diff --git a/clients/roscpp/include/ros/forwards.h b/clients/roscpp/include/ros/forwards.h
index 9095ce5..8ac7406 100644
--- a/clients/roscpp/include/ros/forwards.h
+++ b/clients/roscpp/include/ros/forwards.h
@@ -161,6 +161,24 @@ struct WallTimerEvent
 };
 typedef boost::function<void(const WallTimerEvent&)> WallTimerCallback;
 
+/**
+ * \brief Structure passed as a parameter to the callback invoked by a ros::SteadyTimer
+ */
+struct SteadyTimerEvent
+{
+  SteadyTime last_expected;            ///< In a perfect world, this is when the last callback should have happened
+  SteadyTime last_real;                ///< When the last callback actually happened
+
+  SteadyTime current_expected;         ///< In a perfect world, this is when the current callback should be happening
+  SteadyTime current_real;             ///< This is when the current callback was actually called (SteadyTime::now() as of the beginning of the callback)
+
+  struct
+  {
+    WallDuration last_duration;           ///< How long the last callback ran for
+  } profile;
+};
+typedef boost::function<void(const SteadyTimerEvent&)> SteadyTimerCallback;
+
 class ServiceManager;
 typedef boost::shared_ptr<ServiceManager> ServiceManagerPtr;
 class TopicManager;
diff --git a/clients/roscpp/include/ros/internal_timer_manager.h b/clients/roscpp/include/ros/internal_timer_manager.h
index 5f33dfc..44e23c2 100644
--- a/clients/roscpp/include/ros/internal_timer_manager.h
+++ b/clients/roscpp/include/ros/internal_timer_manager.h
@@ -36,7 +36,7 @@ namespace ros
 {
 
 template<typename T, typename D, typename E> class TimerManager;
-typedef TimerManager<WallTime, WallDuration, WallTimerEvent> InternalTimerManager;
+typedef TimerManager<SteadyTime, WallDuration, SteadyTimerEvent> InternalTimerManager;
 typedef boost::shared_ptr<InternalTimerManager> InternalTimerManagerPtr;
 
 ROSCPP_DECL void initInternalTimerManager();
diff --git a/clients/roscpp/include/ros/master.h b/clients/roscpp/include/ros/master.h
index 9eefdf3..6cabd01 100644
--- a/clients/roscpp/include/ros/master.h
+++ b/clients/roscpp/include/ros/master.h
@@ -29,7 +29,7 @@
 #define ROSCPP_MASTER_H
 
 #include "forwards.h"
-#include "XmlRpcValue.h"
+#include "xmlrpcpp/XmlRpcValue.h"
 #include "common.h"
 
 namespace ros
diff --git a/clients/roscpp/include/ros/node_handle.h b/clients/roscpp/include/ros/node_handle.h
index 4f4c1df..fcb6c78 100644
--- a/clients/roscpp/include/ros/node_handle.h
+++ b/clients/roscpp/include/ros/node_handle.h
@@ -36,6 +36,7 @@
 #include "ros/timer.h"
 #include "ros/rate.h"
 #include "ros/wall_timer.h"
+#include "ros/steady_timer.h"
 #include "ros/advertise_options.h"
 #include "ros/advertise_service_options.h"
 #include "ros/subscribe_options.h"
@@ -48,7 +49,7 @@
 
 #include <boost/bind.hpp>
 
-#include <XmlRpcValue.h>
+#include <xmlrpcpp/XmlRpcValue.h>
 
 namespace ros
 {
@@ -1466,6 +1467,85 @@ if (service)  // Enter if advertised service is valid
    */
   WallTimer createWallTimer(WallTimerOptions& ops) const;
 
+  //////////////////////////////////////////////////////////////////////////////////////////////////////////////
+  // Versions of createSteadyTimer()
+  //////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+  /**
+   * \brief Create a timer which will call a callback at the specified rate, using wall time to determine
+   * when to call the callback instead of ROS time.
+   * This variant takes a class member function, and a bare pointer to the object to call the method on.
+   *
+   * When the Timer (and all copies of it) returned goes out of scope, the timer will automatically
+   * be stopped, and the callback will no longer be called.
+   *
+   * \param period The period at which to call the callback
+   * \param callback The method to call
+   * \param obj The object to call the method on
+   * \param oneshot If true, this timer will only fire once
+   * \param autostart If true (default), return timer that is already started
+   */
+  template<class T>
+  SteadyTimer createSteadyTimer(WallDuration period, void(T::*callback)(const SteadyTimerEvent&), T* obj,
+                                bool oneshot = false, bool autostart = true) const
+  {
+    return createSteadyTimer(period, boost::bind(callback, obj, _1), oneshot, autostart);
+  }
+
+  /**
+   * \brief Create a timer which will call a callback at the specified rate, using wall time to determine
+   * when to call the callback instead of ROS time.  This variant takes
+   * a class member function, and a shared pointer to the object to call the method on.
+   *
+   * When the Timer (and all copies of it) returned goes out of scope, the timer will automatically
+   * be stopped, and the callback will no longer be called.
+   *
+   * \param period The period at which to call the callback
+   * \param callback The method to call
+   * \param obj The object to call the method on.  Since this is a shared pointer, the object will
+   * automatically be tracked with a weak_ptr so that if it is deleted before the Timer goes out of
+   * scope the callback will no longer be called (and therefore will not crash).
+   * \param oneshot If true, this timer will only fire once
+   */
+  template<class T>
+  SteadyTimer createSteadyTimer(WallDuration period, void(T::*callback)(const SteadyTimerEvent&),
+                                const boost::shared_ptr<T>& obj,
+                                bool oneshot = false, bool autostart = true) const
+  {
+    SteadyTimerOptions ops(period, boost::bind(callback, obj.get(), _1), 0);
+    ops.tracked_object = obj;
+    ops.oneshot = oneshot;
+    ops.autostart = autostart;
+    return createSteadyTimer(ops);
+  }
+
+  /**
+   * \brief Create a timer which will call a callback at the specified rate, using wall time to determine
+   * when to call the callback instead of ROS time.  This variant takes
+   * anything that can be bound to a Boost.Function, including a bare function
+   *
+   * When the Timer (and all copies of it) returned goes out of scope, the timer will automatically
+   * be stopped, and the callback will no longer be called.
+   *
+   * \param period The period at which to call the callback
+   * \param callback The function to call
+   * \param oneshot If true, this timer will only fire once
+   */
+  SteadyTimer createSteadyTimer(WallDuration period, const SteadyTimerCallback& callback,
+                                bool oneshot = false, bool autostart = true) const;
+
+  /**
+   * \brief Create a timer which will call a callback at the specified rate, using wall time to determine
+   * when to call the callback instead of ROS time.  This variant allows
+   * the full range of TimerOptions.
+   *
+   * When the Timer (and all copies of it) returned goes out of scope, the timer will automatically
+   * be stopped, and the callback will no longer be called.
+   *
+   * \param ops The options to use when creating the timer
+   */
+  SteadyTimer createSteadyTimer(SteadyTimerOptions& ops) const;
+
   /** \brief Set an arbitrary XML/RPC value on the parameter server.
    *
    * \param key The key to be used in the parameter server's dictionary
diff --git a/clients/roscpp/include/ros/param.h b/clients/roscpp/include/ros/param.h
index cfa7521..699f212 100644
--- a/clients/roscpp/include/ros/param.h
+++ b/clients/roscpp/include/ros/param.h
@@ -30,7 +30,7 @@
 
 #include "forwards.h"
 #include "common.h"
-#include "XmlRpcValue.h"
+#include "xmlrpcpp/XmlRpcValue.h"
 
 #include <vector>
 #include <map>
diff --git a/clients/roscpp/include/ros/publication.h b/clients/roscpp/include/ros/publication.h
index 5183e08..1ea2187 100644
--- a/clients/roscpp/include/ros/publication.h
+++ b/clients/roscpp/include/ros/publication.h
@@ -31,7 +31,7 @@
 #include "ros/forwards.h"
 #include "ros/advertise_options.h"
 #include "common.h"
-#include "XmlRpc.h"
+#include "xmlrpcpp/XmlRpc.h"
 
 #include <boost/thread/mutex.hpp>
 
diff --git a/clients/roscpp/include/ros/service_publication.h b/clients/roscpp/include/ros/service_publication.h
index bd44c34..ff4f8b4 100644
--- a/clients/roscpp/include/ros/service_publication.h
+++ b/clients/roscpp/include/ros/service_publication.h
@@ -30,7 +30,7 @@
 
 #include "ros/service_callback_helper.h"
 #include "common.h"
-#include "XmlRpc.h"
+#include "xmlrpcpp/XmlRpc.h"
 
 #include <boost/thread/mutex.hpp>
 
diff --git a/clients/roscpp/include/ros/steady_timer.h b/clients/roscpp/include/ros/steady_timer.h
new file mode 100644
index 0000000..c16f282
--- /dev/null
+++ b/clients/roscpp/include/ros/steady_timer.h
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2017, Felix Ruess, Roboception GmbH
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *   * Redistributions of source code must retain the above copyright notice,
+ *     this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *   * Neither the names of Stanford University or Willow Garage, Inc. nor the names of its
+ *     contributors may be used to endorse or promote products derived from
+ *     this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ROSCPP_STEADY_TIMER_H
+#define ROSCPP_STEADY_TIMER_H
+
+#include "common.h"
+#include "forwards.h"
+#include "steady_timer_options.h"
+
+namespace ros
+{
+
+/**
+ * \brief Manages a steady-clock timer callback
+ *
+ * A SteadyTimer should always be created through a call to NodeHandle::createSteadyTimer(), or copied from one
+ * that was. Once all copies of a specific
+ * SteadyTimer go out of scope, the callback associated with that handle will stop
+ * being called.
+ */
+class ROSCPP_DECL SteadyTimer
+{
+public:
+  SteadyTimer() {}
+  SteadyTimer(const SteadyTimer& rhs);
+  ~SteadyTimer();
+
+  /**
+   * \brief Start the timer.  Does nothing if the timer is already started.
+   */
+  void start();
+  /**
+   * \brief Stop the timer.  Once this call returns, no more callbacks will be called.  Does
+   * nothing if the timer is already stopped.
+   */
+  void stop();
+
+  /**
+   * \brief Returns whether or not the timer has any pending events to call.
+   */
+  bool hasPending();
+
+  /**
+   * \brief Set the period of this timer
+   */
+  void setPeriod(const WallDuration& period, bool reset=true);
+
+  bool isValid() { return impl_ && impl_->isValid(); }
+  operator void*() { return isValid() ? (void *) 1 : (void *) 0; }
+
+  bool operator<(const SteadyTimer& rhs)
+  {
+    return impl_ < rhs.impl_;
+  }
+
+  bool operator==(const SteadyTimer& rhs)
+  {
+    return impl_ == rhs.impl_;
+  }
+
+  bool operator!=(const SteadyTimer& rhs)
+  {
+    return impl_ != rhs.impl_;
+  }
+
+private:
+  SteadyTimer(const SteadyTimerOptions& ops);
+
+  class Impl
+  {
+  public:
+    Impl();
+    ~Impl();
+
+    bool isValid();
+    bool hasPending();
+    void setPeriod(const WallDuration &period, bool reset=true);
+
+    void start();
+    void stop();
+
+    bool started_;
+    int32_t timer_handle_;
+
+    WallDuration period_;
+    SteadyTimerCallback callback_;
+    CallbackQueueInterface *callback_queue_;
+    VoidConstWPtr tracked_object_;
+    bool has_tracked_object_;
+    bool oneshot_;
+  };
+  typedef boost::shared_ptr<Impl> ImplPtr;
+  typedef boost::weak_ptr<Impl> ImplWPtr;
+
+  ImplPtr impl_;
+
+  friend class NodeHandle;
+};
+
+}
+
+#endif
diff --git a/clients/roscpp/include/ros/steady_timer_options.h b/clients/roscpp/include/ros/steady_timer_options.h
new file mode 100644
index 0000000..e93a973
--- /dev/null
+++ b/clients/roscpp/include/ros/steady_timer_options.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2017, Felix Ruess, Roboception GmbH
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *   * Redistributions of source code must retain the above copyright notice,
+ *     this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *   * Neither the names of Stanford University or Willow Garage, Inc. nor the names of its
+ *     contributors may be used to endorse or promote products derived from
+ *     this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ROSCPP_STEADY_TIMER_OPTIONS_H
+#define ROSCPP_STEADY_TIMER_OPTIONS_H
+
+#include "common.h"
+#include "ros/forwards.h"
+
+namespace ros
+{
+
+/**
+ * \brief Encapsulates all options available for starting a timer
+ */
+struct ROSCPP_DECL SteadyTimerOptions
+{
+  SteadyTimerOptions()
+  : period(0.1)
+  , callback_queue(0)
+  , oneshot(false)
+  , autostart(true)
+  {
+  }
+
+  /*
+   * \brief Constructor
+   * \param
+   */
+  SteadyTimerOptions(WallDuration _period, const SteadyTimerCallback& _callback, CallbackQueueInterface* _queue,
+                     bool oneshot = false, bool autostart = true)
+  : period(_period)
+  , callback(_callback)
+  , callback_queue(_queue)
+  , oneshot(oneshot)
+  , autostart(autostart)
+  {}
+
+  WallDuration period;                                              ///< The period to call the callback at
+  SteadyTimerCallback callback;                                  ///< The callback to call
+
+  CallbackQueueInterface* callback_queue;                           ///< Queue to add callbacks to.  If NULL, the global callback queue will be used
+
+  /**
+   * A shared pointer to an object to track for these callbacks.  If set, the a weak_ptr will be created to this object,
+   * and if the reference count goes to 0 the subscriber callbacks will not get called.
+   *
+   * \note Note that setting this will cause a new reference to be added to the object before the
+   * callback, and for it to go out of scope (and potentially be deleted) in the code path (and therefore
+   * thread) that the callback is invoked from.
+   */
+  VoidConstPtr tracked_object;
+
+  bool oneshot;
+  bool autostart;
+};
+
+
+}
+
+#endif
+
diff --git a/clients/roscpp/include/ros/subscription.h b/clients/roscpp/include/ros/subscription.h
index 7da3219..ed726a3 100644
--- a/clients/roscpp/include/ros/subscription.h
+++ b/clients/roscpp/include/ros/subscription.h
@@ -35,7 +35,7 @@
 #include "ros/transport_hints.h"
 #include "ros/xmlrpc_manager.h"
 #include "ros/statistics.h"
-#include "XmlRpc.h"
+#include "xmlrpcpp/XmlRpc.h"
 
 #include <boost/thread.hpp>
 #include <boost/shared_ptr.hpp>
diff --git a/clients/roscpp/include/ros/timer_manager.h b/clients/roscpp/include/ros/timer_manager.h
index e5da5fc..27f8ca1 100644
--- a/clients/roscpp/include/ros/timer_manager.h
+++ b/clients/roscpp/include/ros/timer_manager.h
@@ -28,6 +28,21 @@
 #ifndef ROSCPP_TIMER_MANAGER_H
 #define ROSCPP_TIMER_MANAGER_H
 
+// check if we might need to include our own backported version boost::condition_variable
+// in order to use CLOCK_MONOTONIC for the SteadyTimer
+// the include order here is important!
+#ifdef BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
+#include <boost/version.hpp>
+#if BOOST_VERSION < 106100
+// use backported version of boost condition variable, see https://svn.boost.org/trac/boost/ticket/6377
+#include "boost_161_condition_variable.h"
+#else // Boost version is 1.61 or greater and has the steady clock fixes
+#include <boost/thread/condition_variable.hpp>
+#endif
+#else // !BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
+#include <boost/thread/condition_variable.hpp>
+#endif // BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
+
 #include "ros/forwards.h"
 #include "ros/time.h"
 #include "ros/file_log.h"
@@ -35,7 +50,6 @@
 #include <boost/thread/thread.hpp>
 #include <boost/thread/mutex.hpp>
 #include <boost/thread/recursive_mutex.hpp>
-#include <boost/thread/condition_variable.hpp>
 
 #include "ros/assert.h"
 #include "ros/callback_queue_interface.h"
@@ -180,9 +194,9 @@ private:
         event.current_real = T::now();
         event.profile.last_duration = info->last_cb_duration;
 
-        WallTime cb_start = WallTime::now();
+        SteadyTime cb_start = SteadyTime::now();
         info->callback(event);
-        WallTime cb_end = WallTime::now();
+        SteadyTime cb_end = SteadyTime::now();
         info->last_cb_duration = cb_end - cb_start;
 
         info->last_real = event.current_real;
diff --git a/clients/roscpp/include/ros/topic_manager.h b/clients/roscpp/include/ros/topic_manager.h
index 5827e82..3a80f9c 100644
--- a/clients/roscpp/include/ros/topic_manager.h
+++ b/clients/roscpp/include/ros/topic_manager.h
@@ -33,7 +33,7 @@
 #include "ros/serialization.h"
 #include "rosout_appender.h"
 
-#include "XmlRpcValue.h"
+#include "xmlrpcpp/XmlRpcValue.h"
 
 #include <boost/thread/mutex.hpp>
 #include <boost/thread/recursive_mutex.hpp>
diff --git a/clients/roscpp/include/ros/transport_publisher_link.h b/clients/roscpp/include/ros/transport_publisher_link.h
index 6ba9624..7d46292 100644
--- a/clients/roscpp/include/ros/transport_publisher_link.h
+++ b/clients/roscpp/include/ros/transport_publisher_link.h
@@ -42,7 +42,7 @@ typedef boost::weak_ptr<Subscription> SubscriptionWPtr;
 class Connection;
 typedef boost::shared_ptr<Connection> ConnectionPtr;
 
-class WallTimerEvent;
+struct SteadyTimerEvent;
 
 /**
  * \brief Handles a connection to a single publisher on a given topic.  Receives messages from a publisher
@@ -76,14 +76,14 @@ private:
   void onMessageLength(const ConnectionPtr& conn, const boost::shared_array<uint8_t>& buffer, uint32_t size, bool success);
   void onMessage(const ConnectionPtr& conn, const boost::shared_array<uint8_t>& buffer, uint32_t size, bool success);
 
-  void onRetryTimer(const ros::WallTimerEvent&);
+  void onRetryTimer(const ros::SteadyTimerEvent&);
 
   ConnectionPtr connection_;
 
   int32_t retry_timer_handle_;
   bool needs_retry_;
   WallDuration retry_period_;
-  WallTime next_retry_;
+  SteadyTime next_retry_;
   bool dropping_;
 };
 typedef boost::shared_ptr<TransportPublisherLink> TransportPublisherLinkPtr;
diff --git a/clients/roscpp/include/ros/xmlrpc_manager.h b/clients/roscpp/include/ros/xmlrpc_manager.h
index 7dc55ee..2dc5034 100644
--- a/clients/roscpp/include/ros/xmlrpc_manager.h
+++ b/clients/roscpp/include/ros/xmlrpc_manager.h
@@ -36,7 +36,7 @@
 #include <boost/enable_shared_from_this.hpp>
 
 #include "common.h"
-#include "XmlRpc.h"
+#include "xmlrpcpp/XmlRpc.h"
 
 #include <ros/time.h>
 
diff --git a/clients/roscpp/package.xml b/clients/roscpp/package.xml
index f8ea44c..eab9479 100644
--- a/clients/roscpp/package.xml
+++ b/clients/roscpp/package.xml
@@ -1,6 +1,6 @@
 <package>
   <name>roscpp</name>
-  <version>1.12.6</version>
+  <version>1.13.1</version>
   <description>
     roscpp is a C++ implementation of ROS. It provides
     a <a href="http://www.ros.org/wiki/Client%20Libraries">client
@@ -31,7 +31,7 @@
   <build_depend version_gte="0.3.17">roscpp_traits</build_depend>
   <build_depend version_gte="1.10.3">rosgraph_msgs</build_depend>
   <build_depend>roslang</build_depend>
-  <build_depend>rostime</build_depend>
+  <build_depend version_gte="0.6.4">rostime</build_depend>
   <build_depend>std_msgs</build_depend>
   <build_depend>xmlrpcpp</build_depend>
 
@@ -41,7 +41,7 @@
   <run_depend>roscpp_serialization</run_depend>
   <run_depend version_gte="0.3.17">roscpp_traits</run_depend>
   <run_depend version_gte="1.10.3">rosgraph_msgs</run_depend>
-  <run_depend>rostime</run_depend>
+  <run_depend version_gte="0.6.4">rostime</run_depend>
   <run_depend>std_msgs</run_depend>
   <run_depend>xmlrpcpp</run_depend>
 </package>
diff --git a/clients/roscpp/src/libros/callback_queue.cpp b/clients/roscpp/src/libros/callback_queue.cpp
index cd2f4f8..5827646 100644
--- a/clients/roscpp/src/libros/callback_queue.cpp
+++ b/clients/roscpp/src/libros/callback_queue.cpp
@@ -102,17 +102,6 @@ void CallbackQueue::addCallback(const CallbackInterfacePtr& callback, uint64_t r
   info.removal_id = removal_id;
 
   {
-    boost::mutex::scoped_lock lock(mutex_);
-
-    if (!enabled_)
-    {
-      return;
-    }
-
-    callbacks_.push_back(info);
-  }
-
-  {
     boost::mutex::scoped_lock lock(id_info_mutex_);
 
     M_IDInfo::iterator it = id_info_.find(removal_id);
@@ -124,6 +113,17 @@ void CallbackQueue::addCallback(const CallbackInterfacePtr& callback, uint64_t r
     }
   }
 
+  {
+    boost::mutex::scoped_lock lock(mutex_);
+
+    if (!enabled_)
+    {
+      return;
+    }
+
+    callbacks_.push_back(info);
+  }
+
   condition_.notify_one();
 }
 
diff --git a/clients/roscpp/src/libros/connection_manager.cpp b/clients/roscpp/src/libros/connection_manager.cpp
index bbba1a6..98789b6 100644
--- a/clients/roscpp/src/libros/connection_manager.cpp
+++ b/clients/roscpp/src/libros/connection_manager.cpp
@@ -209,7 +209,7 @@ bool ConnectionManager::onConnectionHeaderReceived(const ConnectionPtr& conn, co
   std::string val;
   if (header.getValue("topic", val))
   {
-    ROSCPP_LOG_DEBUG("Connection: Creating TransportSubscriberLink for topic [%s] connected to [%s]", 
+    ROSCPP_CONN_LOG_DEBUG("Connection: Creating TransportSubscriberLink for topic [%s] connected to [%s]", 
 		     val.c_str(), conn->getRemoteString().c_str());
 
     TransportSubscriberLinkPtr sub_link(boost::make_shared<TransportSubscriberLink>());
diff --git a/clients/roscpp/src/libros/init.cpp b/clients/roscpp/src/libros/init.cpp
index 8837898..91e0a58 100644
--- a/clients/roscpp/src/libros/init.cpp
+++ b/clients/roscpp/src/libros/init.cpp
@@ -48,7 +48,7 @@
 #include "ros/subscribe_options.h"
 #include "ros/transport/transport_tcp.h"
 #include "ros/internal_timer_manager.h"
-#include "XmlRpcSocket.h"
+#include "xmlrpcpp/XmlRpcSocket.h"
 
 #include "roscpp/GetLoggers.h"
 #include "roscpp/SetLoggerLevel.h"
diff --git a/clients/roscpp/src/libros/internal_timer_manager.cpp b/clients/roscpp/src/libros/internal_timer_manager.cpp
index 5f3ba27..facb417 100644
--- a/clients/roscpp/src/libros/internal_timer_manager.cpp
+++ b/clients/roscpp/src/libros/internal_timer_manager.cpp
@@ -25,8 +25,19 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include "ros/internal_timer_manager.h"
+// make sure we use CLOCK_MONOTONIC for the condition variable
+#define BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
+
 #include "ros/timer_manager.h"
+#include "ros/internal_timer_manager.h"
+
+// check if we have really included the backported boost condition variable
+// just in case someone messes with the include order...
+#if BOOST_VERSION < 106100
+#ifndef USING_BACKPORTED_BOOST_CONDITION_VARIABLE
+#error "steady timer needs boost version >= 1.61 or the backported headers!"
+#endif
+#endif
 
 namespace ros
 {
diff --git a/clients/roscpp/src/libros/master.cpp b/clients/roscpp/src/libros/master.cpp
index d0e4ef4..c0e2e10 100644
--- a/clients/roscpp/src/libros/master.cpp
+++ b/clients/roscpp/src/libros/master.cpp
@@ -34,7 +34,7 @@
 #include <ros/console.h>
 #include <ros/assert.h>
 
-#include "XmlRpc.h"
+#include "xmlrpcpp/XmlRpc.h"
 
 namespace ros
 {
@@ -178,7 +178,7 @@ boost::mutex g_xmlrpc_call_mutex;
 
 bool execute(const std::string& method, const XmlRpc::XmlRpcValue& request, XmlRpc::XmlRpcValue& response, XmlRpc::XmlRpcValue& payload, bool wait_for_master)
 {
-  ros::WallTime start_time = ros::WallTime::now();
+  ros::SteadyTime start_time = ros::SteadyTime::now();
 
   std::string master_host = getHost();
   uint32_t master_port = getPort();
@@ -186,9 +186,9 @@ bool execute(const std::string& method, const XmlRpc::XmlRpcValue& request, XmlR
   bool printed = false;
   bool slept = false;
   bool ok = true;
+  bool b = false;
   do
   {
-    bool b = false;
     {
 #if defined(__APPLE__)
       boost::mutex::scoped_lock lock(g_xmlrpc_call_mutex);
@@ -213,7 +213,7 @@ bool execute(const std::string& method, const XmlRpc::XmlRpcValue& request, XmlR
         return false;
       }
 
-      if (!g_retry_timeout.isZero() && (ros::WallTime::now() - start_time) >= g_retry_timeout)
+      if (!g_retry_timeout.isZero() && (ros::SteadyTime::now() - start_time) >= g_retry_timeout)
       {
         ROS_ERROR("[%s] Timed out trying to connect to the master after [%f] seconds", method.c_str(), g_retry_timeout.toSec());
         XMLRPCManager::instance()->releaseXMLRPCClient(c);
@@ -245,7 +245,7 @@ bool execute(const std::string& method, const XmlRpc::XmlRpcValue& request, XmlR
 
   XMLRPCManager::instance()->releaseXMLRPCClient(c);
 
-  return true;
+  return b;
 }
 
 } // namespace master
diff --git a/clients/roscpp/src/libros/node_handle.cpp b/clients/roscpp/src/libros/node_handle.cpp
index 6673d48..67caeee 100644
--- a/clients/roscpp/src/libros/node_handle.cpp
+++ b/clients/roscpp/src/libros/node_handle.cpp
@@ -29,10 +29,12 @@
 #include "ros/this_node.h"
 #include "ros/service.h"
 #include "ros/callback_queue.h"
-#include "ros/timer_manager.h"
 
 #include "ros/time.h"
 #include "ros/rate.h"
+#include "ros/timer.h"
+#include "ros/wall_timer.h"
+#include "ros/steady_timer.h"
 
 #include "ros/xmlrpc_manager.h"
 #include "ros/topic_manager.h"
@@ -42,7 +44,7 @@
 #include "ros/names.h"
 #include "ros/init.h"
 #include "ros/this_node.h"
-#include "XmlRpc.h"
+#include "xmlrpcpp/XmlRpc.h"
 
 #include <boost/thread.hpp>
 
@@ -449,6 +451,37 @@ WallTimer NodeHandle::createWallTimer(WallTimerOptions& ops) const
   return timer;
 }
 
+SteadyTimer NodeHandle::createSteadyTimer(WallDuration period, const SteadyTimerCallback& callback,
+                                          bool oneshot, bool autostart) const
+{
+  SteadyTimerOptions ops;
+  ops.period = period;
+  ops.callback = callback;
+  ops.oneshot = oneshot;
+  ops.autostart = autostart;
+  return createSteadyTimer(ops);
+}
+
+SteadyTimer NodeHandle::createSteadyTimer(SteadyTimerOptions& ops) const
+{
+  if (ops.callback_queue == 0)
+  {
+    if (callback_queue_)
+    {
+      ops.callback_queue = callback_queue_;
+    }
+    else
+    {
+      ops.callback_queue = getGlobalCallbackQueue();
+    }
+  }
+
+  SteadyTimer timer(ops);
+  if (ops.autostart)
+    timer.start();
+  return timer;
+}
+
 void NodeHandle::shutdown()
 {
   {
diff --git a/clients/roscpp/src/libros/service_manager.cpp b/clients/roscpp/src/libros/service_manager.cpp
index 2bdb022..1f1e94a 100644
--- a/clients/roscpp/src/libros/service_manager.cpp
+++ b/clients/roscpp/src/libros/service_manager.cpp
@@ -42,7 +42,7 @@
 #include "ros/connection.h"
 #include "ros/file_log.h"
 
-#include "XmlRpc.h"
+#include "xmlrpcpp/XmlRpc.h"
 
 #include <ros/console.h>
 
diff --git a/clients/roscpp/src/libros/spinner.cpp b/clients/roscpp/src/libros/spinner.cpp
index 4bae89a..8941c3e 100644
--- a/clients/roscpp/src/libros/spinner.cpp
+++ b/clients/roscpp/src/libros/spinner.cpp
@@ -34,11 +34,6 @@
 
 namespace {
 
-const std::string DEFAULT_ERROR_MESSAGE =
-    "\nAttempt to spin a callback queue from two spinners, one of them being single-threaded."
-    "\nThis will probably result in callbacks being executed out-of-order."
-    "\nIn future this will throw an exception!";
-
 /** class to monitor running single-threaded spinners.
  *
  *  Calling the callbacks of a callback queue _in order_, requires a unique SingleThreadedSpinner
@@ -61,11 +56,9 @@ struct SpinnerMonitor
   */
   struct Entry
   {
-    Entry(const boost::thread::id &tid,
-          const boost::thread::id &initial_tid) : tid(tid), initial_tid(initial_tid), num(0) {}
+    Entry(const boost::thread::id &tid) : tid(tid), num(0) {}
 
     boost::thread::id tid; // proper thread id of single-threaded spinner
-    boost::thread::id initial_tid; // to retain old behaviour, store first spinner's thread id
     unsigned int num; // number of (alike) spinners serving this queue
   };
 
@@ -74,35 +67,19 @@ struct SpinnerMonitor
   {
     boost::mutex::scoped_lock lock(mutex_);
 
-    boost::thread::id current_tid = boost::this_thread::get_id();
     boost::thread::id tid; // current thread id for single-threaded spinners, zero for multi-threaded ones
     if (single_threaded)
-      tid = current_tid;
+      tid = boost::this_thread::get_id();
 
     std::map<ros::CallbackQueue*, Entry>::iterator it = spinning_queues_.find(queue);
     bool can_spin = ( it == spinning_queues_.end() || // we will spin on any new queue
                       it->second.tid == tid ); // otherwise spinner must be alike (all multi-threaded: 0, or single-threaded on same thread id)
 
     if (!can_spin)
-    {
-      // Previous behavior (up to Kinetic) was to accept multiple spinners on a queue
-      // as long as they were started from the same thread. Although this is wrong behavior,
-      // we retain it here for backwards compatibility, i.e. we allow spinning of a
-      // single-threaded spinner after several multi-threaded ones, given that they
-      // were started from the same initial thread
-      if (it->second.initial_tid == tid)
-      {
-        ROS_ERROR_STREAM("SpinnerMonitor: single-threaded spinner after multi-threaded one(s)."
-                         << DEFAULT_ERROR_MESSAGE
-                         << " Only allowed for backwards compatibility.");
-        it->second.tid = tid; // "upgrade" tid to represent single-threaded spinner
-      }
-      else
-        return false;
-    }
+      return false;
 
     if (it == spinning_queues_.end())
-      it = spinning_queues_.insert(it, std::make_pair(queue, Entry(tid, current_tid)));
+      it = spinning_queues_.insert(it, std::make_pair(queue, Entry(tid)));
 
     // increment number of active spinners
     it->second.num += 1;
@@ -135,6 +112,9 @@ struct SpinnerMonitor
 };
 
 SpinnerMonitor spinner_monitor;
+const std::string DEFAULT_ERROR_MESSAGE =
+    "Attempt to spin a callback queue from two spinners, one of them being single-threaded. "
+    "This will probably result in callbacks being executed out-of-order.";
 }
 
 namespace ros
@@ -150,8 +130,8 @@ void SingleThreadedSpinner::spin(CallbackQueue* queue)
 
   if (!spinner_monitor.add(queue, true))
   {
-    ROS_ERROR_STREAM("SingleThreadedSpinner: " << DEFAULT_ERROR_MESSAGE);
-    return;
+    ROS_FATAL_STREAM("SingleThreadedSpinner: " << DEFAULT_ERROR_MESSAGE);
+    throw std::runtime_error("There is already another spinner on this queue");
   }
 
   ros::WallDuration timeout(0.1f);
@@ -240,8 +220,8 @@ void AsyncSpinnerImpl::start()
 
   if (!spinner_monitor.add(callback_queue_, false))
   {
-    ROS_ERROR_STREAM("AsyncSpinnerImpl: " << DEFAULT_ERROR_MESSAGE);
-    return;
+    ROS_FATAL_STREAM("AsyncSpinnerImpl: " << DEFAULT_ERROR_MESSAGE);
+    throw std::runtime_error("There is already a single-threaded spinner on this queue");
   }
 
   continue_ = true;
diff --git a/clients/roscpp/src/libros/steady_timer.cpp b/clients/roscpp/src/libros/steady_timer.cpp
new file mode 100644
index 0000000..7621f42
--- /dev/null
+++ b/clients/roscpp/src/libros/steady_timer.cpp
@@ -0,0 +1,224 @@
+/*
+ * Copyright (C) 2017, Felix Ruess, Roboception GmbH
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *   * Redistributions of source code must retain the above copyright notice,
+ *     this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *   * Neither the names of Stanford University or Willow Garage, Inc. nor the names of its
+ *     contributors may be used to endorse or promote products derived from
+ *     this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// make sure we use CLOCK_MONOTONIC for the condition variable
+#define BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
+
+#include "ros/steady_timer.h"
+#include "ros/timer_manager.h"
+
+// check if we have really included the backported boost condition variable
+// just in case someone messes with the include order...
+#if BOOST_VERSION < 106100
+#ifndef USING_BACKPORTED_BOOST_CONDITION_VARIABLE
+#error "steady timer needs boost version >= 1.61 or the backported headers!"
+#endif
+#endif
+
+namespace ros
+{
+
+// specialization for SteadyTimer, to make sure we use a version with wait_until that uses the monotonic clock
+template<>
+void TimerManager<SteadyTime, WallDuration, SteadyTimerEvent>::threadFunc()
+{
+  SteadyTime current;
+  while (!quit_)
+  {
+    SteadyTime sleep_end;
+
+    boost::mutex::scoped_lock lock(timers_mutex_);
+
+    current = SteadyTime::now();
+
+    {
+      boost::mutex::scoped_lock waitlock(waiting_mutex_);
+
+      if (waiting_.empty())
+      {
+        sleep_end = current + WallDuration(0.1);
+      }
+      else
+      {
+        TimerInfoPtr info = findTimer(waiting_.front());
+
+        while (!waiting_.empty() && info && info->next_expected <= current)
+        {
+          current = SteadyTime::now();
+
+          //ROS_DEBUG("Scheduling timer callback for timer [%d] of period [%f], [%f] off expected", info->handle, info->period.toSec(), (current - info->next_expected).toSec());
+          CallbackInterfacePtr cb(boost::make_shared<TimerQueueCallback>(this, info, info->last_expected, info->last_real, info->next_expected));
+          info->callback_queue->addCallback(cb, (uint64_t)info.get());
+
+          waiting_.pop_front();
+
+          if (waiting_.empty())
+          {
+            break;
+          }
+
+          info = findTimer(waiting_.front());
+        }
+
+        if (info)
+        {
+          sleep_end = info->next_expected;
+        }
+      }
+    }
+
+    while (!new_timer_ && SteadyTime::now() < sleep_end && !quit_)
+    {
+      current = SteadyTime::now();
+
+      if (current >= sleep_end)
+      {
+        break;
+      }
+
+      // requires boost 1.61 for wait_until to actually use the steady clock
+      // see: https://svn.boost.org/trac/boost/ticket/6377
+      boost::chrono::steady_clock::time_point end_tp(boost::chrono::nanoseconds(sleep_end.toNSec()));
+      timers_cond_.wait_until(lock, end_tp);
+    }
+
+    new_timer_ = false;
+  }
+}
+
+SteadyTimer::Impl::Impl()
+  : started_(false)
+  , timer_handle_(-1)
+{ }
+
+SteadyTimer::Impl::~Impl()
+{
+  ROS_DEBUG("SteadyTimer deregistering callbacks.");
+  stop();
+}
+
+void SteadyTimer::Impl::start()
+{
+  if (!started_)
+  {
+    VoidConstPtr tracked_object;
+    if (has_tracked_object_)
+    {
+      tracked_object = tracked_object_.lock();
+    }
+    timer_handle_ = TimerManager<SteadyTime, WallDuration, SteadyTimerEvent>::global().add(period_, callback_, callback_queue_, tracked_object, oneshot_);
+    started_ = true;
+  }
+}
+
+void SteadyTimer::Impl::stop()
+{
+  if (started_)
+  {
+    started_ = false;
+    TimerManager<SteadyTime, WallDuration, SteadyTimerEvent>::global().remove(timer_handle_);
+    timer_handle_ = -1;
+  }
+}
+
+bool SteadyTimer::Impl::isValid()
+{
+  return !period_.isZero();
+}
+
+bool SteadyTimer::Impl::hasPending()
+{
+  if (!isValid() || timer_handle_ == -1)
+  {
+    return false;
+  }
+
+  return TimerManager<SteadyTime, WallDuration, SteadyTimerEvent>::global().hasPending(timer_handle_);
+}
+
+void SteadyTimer::Impl::setPeriod(const WallDuration& period, bool reset)
+{
+  period_ = period;
+  TimerManager<SteadyTime, WallDuration, SteadyTimerEvent>::global().setPeriod(timer_handle_, period, reset);
+}
+
+
+SteadyTimer::SteadyTimer(const SteadyTimerOptions& ops)
+: impl_(new Impl)
+{
+  impl_->period_ = ops.period;
+  impl_->callback_ = ops.callback;
+  impl_->callback_queue_ = ops.callback_queue;
+  impl_->tracked_object_ = ops.tracked_object;
+  impl_->has_tracked_object_ = (ops.tracked_object != NULL);
+  impl_->oneshot_ = ops.oneshot;
+}
+
+SteadyTimer::SteadyTimer(const SteadyTimer& rhs)
+{
+  impl_ = rhs.impl_;
+}
+
+SteadyTimer::~SteadyTimer()
+{
+}
+
+void SteadyTimer::start()
+{
+  if (impl_)
+  {
+    impl_->start();
+  }
+}
+
+void SteadyTimer::stop()
+{
+  if (impl_)
+  {
+    impl_->stop();
+  }
+}
+
+bool SteadyTimer::hasPending()
+{
+  if (impl_)
+  {
+    return impl_->hasPending();
+  }
+
+  return false;
+}
+
+void SteadyTimer::setPeriod(const WallDuration& period, bool reset)
+{
+  if (impl_)
+  {
+    impl_->setPeriod(period, reset);
+  }
+}
+
+}
diff --git a/clients/roscpp/src/libros/subscription.cpp b/clients/roscpp/src/libros/subscription.cpp
index d2163d7..9a9e71e 100644
--- a/clients/roscpp/src/libros/subscription.cpp
+++ b/clients/roscpp/src/libros/subscription.cpp
@@ -224,10 +224,13 @@ bool Subscription::pubUpdate(const V_string& new_pubs)
     }
 
     ss << " already have these connections: ";
-    for (V_PublisherLink::iterator spc = publisher_links_.begin();
-         spc!= publisher_links_.end(); ++spc)
     {
-      ss << (*spc)->getPublisherXMLRPCURI() << ", ";
+      boost::mutex::scoped_lock lock(publisher_links_mutex_);
+      for (V_PublisherLink::iterator spc = publisher_links_.begin();
+           spc!= publisher_links_.end(); ++spc)
+      {
+        ss << (*spc)->getPublisherXMLRPCURI() << ", ";
+      }
     }
 
     boost::mutex::scoped_lock lock(pending_connections_mutex_);
@@ -503,7 +506,7 @@ void Subscription::pendingConnectionDone(const PendingConnectionPtr& conn, XmlRp
     }
     std::string pub_host = proto[1];
     int pub_port = proto[2];
-    ROSCPP_LOG_DEBUG("Connecting via tcpros to topic [%s] at host [%s:%d]", name_.c_str(), pub_host.c_str(), pub_port);
+    ROSCPP_CONN_LOG_DEBUG("Connecting via tcpros to topic [%s] at host [%s:%d]", name_.c_str(), pub_host.c_str(), pub_port);
 
     TransportTCPPtr transport(boost::make_shared<TransportTCP>(&PollManager::instance()->getPollSet()));
     if (transport->connect(pub_host, pub_port))
@@ -519,11 +522,11 @@ void Subscription::pendingConnectionDone(const PendingConnectionPtr& conn, XmlRp
       boost::mutex::scoped_lock lock(publisher_links_mutex_);
       addPublisherLink(pub_link);
 
-      ROSCPP_LOG_DEBUG("Connected to publisher of topic [%s] at [%s:%d]", name_.c_str(), pub_host.c_str(), pub_port);
+      ROSCPP_CONN_LOG_DEBUG("Connected to publisher of topic [%s] at [%s:%d]", name_.c_str(), pub_host.c_str(), pub_port);
     }
     else
     {
-    	ROSCPP_LOG_DEBUG("Failed to connect to publisher of topic [%s] at [%s:%d]", name_.c_str(), pub_host.c_str(), pub_port);
+      ROSCPP_CONN_LOG_DEBUG("Failed to connect to publisher of topic [%s] at [%s:%d]", name_.c_str(), pub_host.c_str(), pub_port);
     }
   }
   else if (proto_name == "UDPROS")
diff --git a/clients/roscpp/src/libros/this_node.cpp b/clients/roscpp/src/libros/this_node.cpp
index 7f15d73..d27e1ad 100644
--- a/clients/roscpp/src/libros/this_node.cpp
+++ b/clients/roscpp/src/libros/this_node.cpp
@@ -140,17 +140,12 @@ void ThisNode::init(const std::string& name, const M_string& remappings, uint32_
     namespace_ = it->second;
   }
 
-  if (namespace_.empty())
+  namespace_ = names::clean(namespace_);
+  if (namespace_.empty() || (namespace_[0] != '/'))
   {
-    namespace_ = "/";
+    namespace_ = "/" + namespace_;
   }
 
-  namespace_ = (namespace_ == "/")
-    ? std::string("/") 
-    : ("/" + namespace_)
-    ;
-
-
   std::string error;
   if (!names::validate(namespace_, error))
   {
diff --git a/clients/roscpp/src/libros/topic_manager.cpp b/clients/roscpp/src/libros/topic_manager.cpp
index 3d77e7c..363fb05 100644
--- a/clients/roscpp/src/libros/topic_manager.cpp
+++ b/clients/roscpp/src/libros/topic_manager.cpp
@@ -41,7 +41,7 @@
 #include "ros/file_log.h"
 #include "ros/subscribe_options.h"
 
-#include "XmlRpc.h"
+#include "xmlrpcpp/XmlRpc.h"
 
 #include <ros/console.h>
 
diff --git a/clients/roscpp/src/libros/transport/transport_tcp.cpp b/clients/roscpp/src/libros/transport/transport_tcp.cpp
index f061fc2..9605dbb 100644
--- a/clients/roscpp/src/libros/transport/transport_tcp.cpp
+++ b/clients/roscpp/src/libros/transport/transport_tcp.cpp
@@ -311,11 +311,12 @@ bool TransportTCP::connect(const std::string& host, int port)
 
   int ret = ::connect(sock_, (sockaddr*) &sas, sas_len);
   // windows might need some time to sleep (input from service robotics hack) add this if testing proves it is necessary.
-  ROS_ASSERT((flags_ & SYNCHRONOUS) || ret != 0);
+  // ROS_ASSERT((flags_ & SYNCHRONOUS) || ret != 0);
   if (((flags_ & SYNCHRONOUS) && ret != 0) || // synchronous, connect() should return 0
-      (!(flags_ & SYNCHRONOUS) && last_socket_error() != ROS_SOCKETS_ASYNCHRONOUS_CONNECT_RETURN)) // asynchronous, connect() should return -1 and WSAGetLastError()=WSAEWOULDBLOCK/errno=EINPROGRESS
+      (!(flags_ & SYNCHRONOUS) && ret != 0 && last_socket_error() != ROS_SOCKETS_ASYNCHRONOUS_CONNECT_RETURN)) 
+      // asynchronous, connect() may return 0 or -1. When return -1, WSAGetLastError()=WSAEWOULDBLOCK/errno=EINPROGRESS
   {
-    ROSCPP_LOG_DEBUG("Connect to tcpros publisher [%s:%d] failed with error [%d, %s]", host.c_str(), port, ret, last_socket_error_string());
+    ROSCPP_CONN_LOG_DEBUG("Connect to tcpros publisher [%s:%d] failed with error [%d, %s]", host.c_str(), port, ret, last_socket_error_string());
     close();
 
     return false;
@@ -340,11 +341,11 @@ bool TransportTCP::connect(const std::string& host, int port)
 
   if (flags_ & SYNCHRONOUS)
   {
-    ROSCPP_LOG_DEBUG("connect() succeeded to [%s:%d] on socket [%d]", host.c_str(), port, sock_);
+    ROSCPP_CONN_LOG_DEBUG("connect() succeeded to [%s:%d] on socket [%d]", host.c_str(), port, sock_);
   }
   else
   {
-    ROSCPP_LOG_DEBUG("Async connect() in progress to [%s:%d] on socket [%d]", host.c_str(), port, sock_);
+    ROSCPP_CONN_LOG_DEBUG("Async connect() in progress to [%s:%d] on socket [%d]", host.c_str(), port, sock_);
   }
 
   return true;
diff --git a/clients/roscpp/src/libros/transport/transport_udp.cpp b/clients/roscpp/src/libros/transport/transport_udp.cpp
index 848893b..47d969e 100644
--- a/clients/roscpp/src/libros/transport/transport_udp.cpp
+++ b/clients/roscpp/src/libros/transport/transport_udp.cpp
@@ -48,6 +48,9 @@
 #elif defined(__ANDROID__)
   // For readv() and writev() on ANDROID
   #include <sys/uio.h>
+#elif defined(_POSIX_VERSION)
+  // For readv() and writev()
+  #include <sys/uio.h>
 #endif
 
 namespace ros
@@ -590,6 +593,7 @@ int32_t TransportUDP::write(uint8_t* buffer, uint32_t size)
       else
       {
         num_bytes = 0;
+        --this_block;
       }
     }
     else if (num_bytes < (unsigned) sizeof(header))
diff --git a/clients/roscpp/src/libros/transport_publisher_link.cpp b/clients/roscpp/src/libros/transport_publisher_link.cpp
index 6b28f68..092585d 100644
--- a/clients/roscpp/src/libros/transport_publisher_link.cpp
+++ b/clients/roscpp/src/libros/transport_publisher_link.cpp
@@ -198,14 +198,14 @@ void TransportPublisherLink::onMessage(const ConnectionPtr& conn, const boost::s
   }
 }
 
-void TransportPublisherLink::onRetryTimer(const ros::WallTimerEvent&)
+void TransportPublisherLink::onRetryTimer(const ros::SteadyTimerEvent&)
 {
   if (dropping_)
   {
     return;
   }
 
-  if (needs_retry_ && WallTime::now() > next_retry_)
+  if (needs_retry_ && SteadyTime::now() > next_retry_)
   {
     retry_period_ = std::min(retry_period_ * 2, WallDuration(20));
     needs_retry_ = false;
@@ -223,7 +223,7 @@ void TransportPublisherLink::onRetryTimer(const ros::WallTimerEvent&)
       const std::string& host = old_transport->getConnectedHost();
       int port = old_transport->getConnectedPort();
 
-      ROSCPP_LOG_DEBUG("Retrying connection to [%s:%d] for topic [%s]", host.c_str(), port, topic.c_str());
+      ROSCPP_CONN_LOG_DEBUG("Retrying connection to [%s:%d] for topic [%s]", host.c_str(), port, topic.c_str());
 
       TransportTCPPtr transport(boost::make_shared<TransportTCP>(&PollManager::instance()->getPollSet()));
       if (transport->connect(host, port))
@@ -236,7 +236,7 @@ void TransportPublisherLink::onRetryTimer(const ros::WallTimerEvent&)
       }
       else
       {
-        ROSCPP_LOG_DEBUG("connect() failed when retrying connection to [%s:%d] for topic [%s]", host.c_str(), port, topic.c_str());
+        ROSCPP_CONN_LOG_DEBUG("connect() failed when retrying connection to [%s:%d] for topic [%s]", host.c_str(), port, topic.c_str());
       }
     }
     else if (parent)
@@ -264,16 +264,16 @@ void TransportPublisherLink::onConnectionDropped(const ConnectionPtr& conn, Conn
   {
     std::string topic = parent ? parent->getName() : "unknown";
 
-    ROSCPP_LOG_DEBUG("Connection to publisher [%s] to topic [%s] dropped", connection_->getTransport()->getTransportInfo().c_str(), topic.c_str());
+    ROSCPP_CONN_LOG_DEBUG("Connection to publisher [%s] to topic [%s] dropped", connection_->getTransport()->getTransportInfo().c_str(), topic.c_str());
 
     ROS_ASSERT(!needs_retry_);
     needs_retry_ = true;
-    next_retry_ = WallTime::now() + retry_period_;
+    next_retry_ = SteadyTime::now() + retry_period_;
 
     if (retry_timer_handle_ == -1)
     {
       retry_period_ = WallDuration(0.1);
-      next_retry_ = WallTime::now() + retry_period_;
+      next_retry_ = SteadyTime::now() + retry_period_;
       // shared_from_this() shared_ptr is used to ensure TransportPublisherLink is not
       // destroyed in the middle of onRetryTimer execution
       retry_timer_handle_ = getInternalTimerManager()->add(WallDuration(retry_period_),
diff --git a/clients/roscpp/src/libros/transport_subscriber_link.cpp b/clients/roscpp/src/libros/transport_subscriber_link.cpp
index 2257a9a..898b9ec 100644
--- a/clients/roscpp/src/libros/transport_subscriber_link.cpp
+++ b/clients/roscpp/src/libros/transport_subscriber_link.cpp
@@ -128,7 +128,7 @@ void TransportSubscriberLink::onConnectionDropped(const ConnectionPtr& conn)
 
   if (parent)
   {
-    ROSCPP_LOG_DEBUG("Connection to subscriber [%s] to topic [%s] dropped", connection_->getRemoteString().c_str(), topic_.c_str());
+    ROSCPP_CONN_LOG_DEBUG("Connection to subscriber [%s] to topic [%s] dropped", connection_->getRemoteString().c_str(), topic_.c_str());
 
     parent->removeSubscriberLink(shared_from_this());
   }
diff --git a/clients/roscpp/src/libros/xmlrpc_manager.cpp b/clients/roscpp/src/libros/xmlrpc_manager.cpp
index 272315b..6a3829f 100644
--- a/clients/roscpp/src/libros/xmlrpc_manager.cpp
+++ b/clients/roscpp/src/libros/xmlrpc_manager.cpp
@@ -155,20 +155,31 @@ void XMLRPCManager::shutdown()
   server_.close();
 
   // kill the last few clients that were started in the shutdown process
-  for (V_CachedXmlRpcClient::iterator i = clients_.begin();
-       i != clients_.end(); ++i)
   {
-    for (int wait_count = 0; i->in_use_ && wait_count < 10; wait_count++)
+    boost::mutex::scoped_lock lock(clients_mutex_);
+
+    for (V_CachedXmlRpcClient::iterator i = clients_.begin();
+         i != clients_.end();)
     {
-      ROSCPP_LOG_DEBUG("waiting for xmlrpc connection to finish...");
-      ros::WallDuration(0.01).sleep();
+      if (!i->in_use_)
+      {
+        i->client_->close();
+        delete i->client_;
+        i = clients_.erase(i);
+      }
+      else
+      {
+        ++i;
+      }
     }
-
-    i->client_->close();
-    delete i->client_;
   }
 
-  clients_.clear();
+  // Wait for the clients that are in use to finish and remove themselves from clients_
+  for (int wait_count = 0; !clients_.empty() && wait_count < 10; wait_count++)
+  {
+    ROSCPP_LOG_DEBUG("waiting for xmlrpc connection to finish...");
+    ros::WallDuration(0.01).sleep();
+  }
 
   boost::mutex::scoped_lock lock(functions_mutex_);
   functions_.clear();
@@ -369,7 +380,17 @@ void XMLRPCManager::releaseXMLRPCClient(XmlRpcClient *c)
   {
     if (c == i->client_)
     {
-      i->in_use_ = false;
+      if (shutting_down_)
+      {
+        // if we are shutting down we won't be re-using the client
+        i->client_->close();
+        delete i->client_;
+        clients_.erase(i);
+      }
+      else
+      {
+        i->in_use_ = false;
+      }
       break;
     }
   }
diff --git a/clients/rospy/CHANGELOG.rst b/clients/rospy/CHANGELOG.rst
index b8ac0e8..a236d6e 100644
--- a/clients/rospy/CHANGELOG.rst
+++ b/clients/rospy/CHANGELOG.rst
@@ -2,6 +2,26 @@
 Changelog for package rospy
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
+1.13.1 (2017-07-27)
+-------------------
+* improve rospy.logXXX_throttle performance (`#1091 <https://github.com/ros/ros_comm/pull/1091>`_)
+* add option to reset timer when time moved backwards (`#1083 <https://github.com/ros/ros_comm/issues/1083>`_)
+* abort topic lookup on connection refused (`#1044 <https://github.com/ros/ros_comm/pull/1044>`_)
+* add rospy.logXXX_once (`#1041 <https://github.com/ros/ros_comm/issues/1041>`_)
+* remove "ROS time moved backwards" log message (`#1027 <https://github.com/ros/ros_comm/pull/1027>`_)
+* sleep in rospy wait_for_service even if exceptions raised (`#1025 <https://github.com/ros/ros_comm/pull/1025>`_)
+* add named loggers (`#948 <https://github.com/ros/ros_comm/pull/948>`_)
+
+1.13.0 (2017-02-22)
+-------------------
+
+1.12.7 (2017-02-17)
+-------------------
+* make get_published_topics threadsafe (`#958 <https://github.com/ros/ros_comm/issues/958>`_)
+* use poll in write_header() if available to support higher numbered fileno (`#929 <https://github.com/ros/ros_comm/pull/929>`_)
+* use epoll instead of poll if available to gracefully close hung connections (`#831 <https://github.com/ros/ros_comm/issues/831>`_)
+* fix Python 3 compatibility issues (`#565 <https://github.com/ros/ros_comm/issues/565>`_)
+
 1.12.6 (2016-10-26)
 -------------------
 * improve reconnection logic on timeout and other common errors (`#851 <https://github.com/ros/ros_comm/pull/851>`_)
diff --git a/clients/rospy/package.xml b/clients/rospy/package.xml
index e0ca818..677b39e 100644
--- a/clients/rospy/package.xml
+++ b/clients/rospy/package.xml
@@ -1,6 +1,6 @@
 <package>
   <name>rospy</name>
-  <version>1.12.6</version>
+  <version>1.13.1</version>
   <description>
     rospy is a pure Python client library for ROS. The rospy client
     API enables Python programmers to quickly interface with ROS <a
diff --git a/clients/rospy/src/rospy/__init__.py b/clients/rospy/src/rospy/__init__.py
index 337e8f7..4846f7c 100644
--- a/clients/rospy/src/rospy/__init__.py
+++ b/clients/rospy/src/rospy/__init__.py
@@ -58,6 +58,7 @@ from .core import is_shutdown, signal_shutdown, \
     get_node_uri, get_ros_root, \
     logdebug, logwarn, loginfo, logout, logerr, logfatal, \
     logdebug_throttle, logwarn_throttle, loginfo_throttle, logerr_throttle, logfatal_throttle, \
+    logdebug_once, logwarn_once, loginfo_once, logerr_once, logfatal_once, \
     parse_rosrpc_uri
 from .exceptions import *
 from .msg import AnyMsg
@@ -105,6 +106,9 @@ __all__ = [
     'logdebug_throttle',
     'logwarn_throttle', 'loginfo_throttle',
     'logerr_throttle', 'logfatal_throttle',
+    'logdebug_once',
+    'logwarn_once', 'loginfo_once',
+    'logerr_once', 'logfatal_once',
     'parse_rosrpc_uri',
     'MasterProxy',
     'NodeProxy',    
diff --git a/clients/rospy/src/rospy/client.py b/clients/rospy/src/rospy/client.py
index f167ee4..d543c53 100644
--- a/clients/rospy/src/rospy/client.py
+++ b/clients/rospy/src/rospy/client.py
@@ -491,7 +491,14 @@ def set_param(param_name, param_value):
     Set a parameter on the param server
 
     NOTE: this method is thread-safe.
-    
+    If param_value is a dictionary it will be treated as a parameter
+    tree, where param_name is the namespace. For example:::
+      {'x':1,'y':2,'sub':{'z':3}}
+    will set param_name/x=1, param_name/y=2, and param_name/sub/z=3.
+    Furthermore, it will replace all existing parameters in the
+    param_name namespace with the parameters in param_value. You must
+    set parameters individually if you wish to perform a union update.
+
     @param param_name: parameter name
     @type  param_name: str
     @param param_value: parameter value
diff --git a/clients/rospy/src/rospy/core.py b/clients/rospy/src/rospy/core.py
index 57c07b8..ed838fe 100644
--- a/clients/rospy/src/rospy/core.py
+++ b/clients/rospy/src/rospy/core.py
@@ -72,6 +72,7 @@ from rospy.names import *
 from rospy.impl.validators import ParameterInvalid
 
 from rosgraph_msgs.msg import Log
+from functools import partial
 
 _logger = logging.getLogger("rospy.core")
 
@@ -143,17 +144,38 @@ def rospywarn(msg, *args):
     """Internal rospy client library warn logging"""
     _rospy_logger.warn(msg, *args)
     
-logdebug = logging.getLogger('rosout').debug
-
-logwarn = logging.getLogger('rosout').warning
-
-loginfo = logging.getLogger('rosout').info
-logout = loginfo # alias deprecated name
-
-logerr = logging.getLogger('rosout').error
-logerror = logerr # alias logerr
-
-logfatal = logging.getLogger('rosout').critical
+
+def _base_logger(msg, *args, **kwargs):
+
+    name = kwargs.pop('logger_name', None)
+    throttle = kwargs.pop('logger_throttle', None)
+    level = kwargs.pop('logger_level', None)
+                    
+    rospy_logger = logging.getLogger('rosout')
+    if name:
+        rospy_logger = rospy_logger.getChild(name)
+    logfunc = getattr(rospy_logger, level)
+
+    if throttle:
+        caller_id = _frame_to_caller_id(inspect.currentframe().f_back.f_back)
+        _logging_throttle(caller_id, logfunc, throttle, msg, *args)
+    else:
+        logfunc(msg, *args)
+
+
+loginfo = partial(_base_logger, logger_level='info')
+
+logout = loginfo # alias deprecated name
+
+logdebug = partial(_base_logger, logger_level='debug')
+
+logwarn = partial(_base_logger, logger_level='warn')
+
+logerr = partial(_base_logger, logger_level='error')
+
+logerror = logerr # alias logerr
+
+logfatal = partial(_base_logger, logger_level='critical')
 
 
 class LoggingThrottle(object):
@@ -181,39 +203,66 @@ class LoggingThrottle(object):
 _logging_throttle = LoggingThrottle()
 
 
-def _frame_record_to_caller_id(frame_record):
-    frame, _, lineno, _, code, _ = frame_record
+def _frame_to_caller_id(frame):
     caller_id = (
         inspect.getabsfile(frame),
-        lineno,
+        frame.f_lineno,
         frame.f_lasti,
     )
     return pickle.dumps(caller_id)
 
 
 def logdebug_throttle(period, msg):
-    caller_id = _frame_record_to_caller_id(inspect.stack()[1])
-    _logging_throttle(caller_id, logdebug, period, msg)
+    logdebug(msg, logger_name=None, logger_throttle=period)
+      
+def loginfo_throttle(period, msg):
+    loginfo(msg, logger_name=None, logger_throttle=period)
+              
+def logwarn_throttle(period, msg):
+    logwarn(msg, logger_name=None, logger_throttle=period)
 
+def logerr_throttle(period, msg):
+    logerr(msg, logger_name=None, logger_throttle=period)
+                              
+def logfatal_throttle(period, msg):
+    logfatal(msg, logger_name=None, logger_throttle=period)
 
-def loginfo_throttle(period, msg):
-    caller_id = _frame_record_to_caller_id(inspect.stack()[1])
-    _logging_throttle(caller_id, loginfo, period, msg)
+class LoggingOnce(object):
 
+    called_caller_ids = set()
 
-def logwarn_throttle(period, msg):
-    caller_id = _frame_record_to_caller_id(inspect.stack()[1])
-    _logging_throttle(caller_id, logwarn, period, msg)
+    def __call__(self, caller_id, logging_func, msg):
+        if caller_id not in self.called_caller_ids:
+            logging_func(msg)
+            self.called_caller_ids.add(caller_id)
 
 
-def logerr_throttle(period, msg):
-    caller_id = _frame_record_to_caller_id(inspect.stack()[1])
-    _logging_throttle(caller_id, logerr, period, msg)
+_logging_once = LoggingOnce()
 
 
-def logfatal_throttle(period, msg):
-    caller_id = _frame_record_to_caller_id(inspect.stack()[1])
-    _logging_throttle(caller_id, logfatal, period, msg)
+def logdebug_once(msg):
+    caller_id = _frame_to_caller_id(inspect.currentframe().f_back)
+    _logging_once(caller_id, logdebug, msg)
+
+
+def loginfo_once(msg):
+    caller_id = _frame_to_caller_id(inspect.currentframe().f_back)
+    _logging_once(caller_id, loginfo, msg)
+
+
+def logwarn_once(msg):
+    caller_id = _frame_to_caller_id(inspect.currentframe().f_back)
+    _logging_once(caller_id, logwarn, msg)
+
+
+def logerr_once(msg):
+    caller_id = _frame_to_caller_id(inspect.currentframe().f_back)
+    _logging_once(caller_id, logerr, msg)
+
+
+def logfatal_once(msg):
+    caller_id = _frame_to_caller_id(inspect.currentframe().f_back)
+    _logging_once(caller_id, logfatal, msg)
 
 
 #########################################################
diff --git a/clients/rospy/src/rospy/impl/masterslave.py b/clients/rospy/src/rospy/impl/masterslave.py
index d25261c..ad8b214 100644
--- a/clients/rospy/src/rospy/impl/masterslave.py
+++ b/clients/rospy/src/rospy/impl/masterslave.py
@@ -59,6 +59,7 @@ import socket
 import threading
 import traceback
 import time
+import errno
 
 try:
     #py3k
@@ -441,13 +442,19 @@ class ROSHandler(XmlRpcHandler):
         interval = 0.5  # seconds
         # while the ROS node is not shutdown try to get the topic information
         # and retry on connections problems after some wait
+        # Abort the retry if the we get a Connection Refused since at that point
+        # we know for sure the URI is invalid
         while not success and not is_shutdown():
             try:
                 code, msg, result = \
                       xmlrpcapi(pub_uri).requestTopic(caller_id, topic, protocols)
                 success = True
             except Exception as e:
-                if not is_shutdown():
+                if getattr(e, 'errno', None) == errno.ECONNREFUSED:
+                    code = -errno.ECONNREFUSED
+                    msg = str(e)
+                    break
+                elif not is_shutdown():
                     _logger.debug("Retrying for %s" % topic)
                     if interval < 30.0:
                         # exponential backoff (maximum 32 seconds)
diff --git a/clients/rospy/src/rospy/impl/registration.py b/clients/rospy/src/rospy/impl/registration.py
index c29913b..1135a25 100644
--- a/clients/rospy/src/rospy/impl/registration.py
+++ b/clients/rospy/src/rospy/impl/registration.py
@@ -306,6 +306,8 @@ class RegManager(RegistrationListener):
                 if cond is not None:
                     cond.release()
 
+            get_topic_manager().check_all()
+
             #call _connect_topic on all URIs as it can check to see whether
             #or not a connection exists.
             if uris and not self.handler.done:
diff --git a/clients/rospy/src/rospy/impl/tcpros_base.py b/clients/rospy/src/rospy/impl/tcpros_base.py
index 134af0a..7cb0868 100644
--- a/clients/rospy/src/rospy/impl/tcpros_base.py
+++ b/clients/rospy/src/rospy/impl/tcpros_base.py
@@ -613,11 +613,29 @@ class TCPROSTransport(Transport):
             return
         fileno = sock.fileno()
         ready = None
-        while not ready:
-            _, ready, _ = select.select([], [fileno], [])
+        poller = None
+        if hasattr(select, 'poll'):
+            poller = select.poll()
+            poller.register(fileno, select.POLLOUT)
+            while not ready:
+                events = poller.poll()
+                for _, flag in events:
+                  if flag & select.POLLOUT:
+                        ready = True
+        else:
+            while not ready:
+                try:
+                    _, ready, _ = select.select([], [fileno], [])
+                except ValueError as e:
+                    logger.error("[%s]: select fileno '%s': %s", self.name, str(fileno), str(e))
+                    raise
+
         logger.debug("[%s]: writing header", self.name)
         sock.setblocking(1)
         self.stat_bytes += write_ros_handshake_header(sock, protocol.get_header_fields())
+        if poller:
+            poller.unregister(fileno)
+
 
     def read_header(self):
         """
diff --git a/clients/rospy/src/rospy/impl/tcpros_service.py b/clients/rospy/src/rospy/impl/tcpros_service.py
index d720995..034fad3 100644
--- a/clients/rospy/src/rospy/impl/tcpros_service.py
+++ b/clients/rospy/src/rospy/impl/tcpros_service.py
@@ -128,7 +128,6 @@ def wait_for_service(service, timeout=None):
             try:
                 if contact_service(resolved_name, timeout_t-time.time()):
                     return
-                time.sleep(0.3)
             except KeyboardInterrupt:
                 # re-raise
                 rospy.core.logdebug("wait_for_service: received keyboard interrupt, assuming signals disabled and re-raising")
@@ -137,6 +136,7 @@ def wait_for_service(service, timeout=None):
                 if first:
                     first = False
                     rospy.core.logerr("wait_for_service(%s): failed to contact [%s], will keep trying"%(resolved_name, uri))
+            time.sleep(0.3)
         if rospy.core.is_shutdown():
             raise ROSInterruptException("rospy shutdown")
         else:
@@ -146,7 +146,6 @@ def wait_for_service(service, timeout=None):
             try:
                 if contact_service(resolved_name):
                     return
-                time.sleep(0.3)
             except KeyboardInterrupt:
                 # re-raise
                 rospy.core.logdebug("wait_for_service: received keyboard interrupt, assuming signals disabled and re-raising")
@@ -155,6 +154,7 @@ def wait_for_service(service, timeout=None):
                 if first:
                     first = False
                     rospy.core.logerr("wait_for_service(%s): failed to contact [%s], will keep trying"%(resolved_name, uri))
+            time.sleep(0.3)
         if rospy.core.is_shutdown():
             raise ROSInterruptException("rospy shutdown")
     
@@ -608,6 +608,8 @@ class ServiceImpl(_Service):
         @param err_msg: error message to send to client
         @type  err_msg: str
         """
+        if sys.hexversion > 0x03000000: #Python3
+            err_msg = bytes(err_msg, 'utf-8')
         transport.write_data(struct.pack('<BI%ss'%len(err_msg), 0, len(err_msg), err_msg))
 
     def _handle_request(self, transport, request):
diff --git a/clients/rospy/src/rospy/msproxy.py b/clients/rospy/src/rospy/msproxy.py
index c44176c..936f221 100644
--- a/clients/rospy/src/rospy/msproxy.py
+++ b/clients/rospy/src/rospy/msproxy.py
@@ -90,8 +90,6 @@ class MasterProxy(object):
         self._lock = Lock()
 
     def __getattr__(self, key): #forward api calls to target
-        with self._lock:
-            f = getattr(self.target, key)
         if key in _master_arg_remap:
             remappings = _master_arg_remap[key]
         else:
@@ -103,7 +101,9 @@ class MasterProxy(object):
                 i = i + 1 #callerId does not count
                 #print "Remap %s => %s"%(args[i], rospy.names.resolve_name(args[i]))
                 args[i] = rospy.names.resolve_name(args[i])
-            return f(*args, **kwds)
+            with self._lock:
+                f = getattr(self.target, key)
+                return f(*args, **kwds)
         return wrappedF
 
     def __getitem__(self, key):
diff --git a/clients/rospy/src/rospy/timer.py b/clients/rospy/src/rospy/timer.py
index b587426..571f095 100644
--- a/clients/rospy/src/rospy/timer.py
+++ b/clients/rospy/src/rospy/timer.py
@@ -49,15 +49,18 @@ class Rate(object):
     Convenience class for sleeping in a loop at a specified rate
     """
     
-    def __init__(self, hz):
+    def __init__(self, hz, reset=False):
         """
         Constructor.
         @param hz: hz rate to determine sleeping
         @type  hz: int
+        @param reset: if True, timer is reset when rostime moved backward. [default: False]
+        @type  reset: bool
         """
         # #1403
         self.last_time = rospy.rostime.get_rostime()
         self.sleep_dur = rospy.rostime.Duration(0, int(1e9/hz))
+        self._reset = reset
 
     def _remaining(self, curr_time):
         """
@@ -96,7 +99,13 @@ class Rate(object):
         backwards
         """
         curr_time = rospy.rostime.get_rostime()
-        sleep(self._remaining(curr_time))
+        try:
+            sleep(self._remaining(curr_time))
+        except rospy.exceptions.ROSTimeMovedBackwardsException:
+            if not self._reset:
+                raise
+            self.last_time = rospy.rostime.get_rostime()
+            return
         self.last_time = self.last_time + self.sleep_dur
 
         # detect time jumping forwards, as well as loops that are
@@ -151,7 +160,6 @@ def sleep(duration):
 
         if rospy.rostime.get_rostime() < initial_rostime:
             time_jump = (initial_rostime - rospy.rostime.get_rostime()).to_sec()
-            rospy.core.logerr("ROS time moved backwards: %ss", time_jump)
             raise rospy.exceptions.ROSTimeMovedBackwardsException(time_jump)
         if rospy.core.is_shutdown():
             raise rospy.exceptions.ROSInterruptException("ROS shutdown request")
@@ -181,7 +189,7 @@ class Timer(threading.Thread):
     Convenience class for calling a callback at a specified rate
     """
 
-    def __init__(self, period, callback, oneshot=False):
+    def __init__(self, period, callback, oneshot=False, reset=False):
         """
         Constructor.
         @param period: desired period between callbacks
@@ -190,11 +198,14 @@ class Timer(threading.Thread):
         @type  callback: function taking rospy.TimerEvent
         @param oneshot: if True, fire only once, otherwise fire continuously until shutdown is called [default: False]
         @type  oneshot: bool
+        @param reset: if True, timer is reset when rostime moved backward. [default: False]
+        @type  reset: bool
         """
         super(Timer, self).__init__()
         self._period   = period
         self._callback = callback
         self._oneshot  = oneshot
+        self._reset = reset
         self._shutdown = False
         self.setDaemon(True)
         self.start()
@@ -206,7 +217,7 @@ class Timer(threading.Thread):
         self._shutdown = True
         
     def run(self):
-        r = Rate(1.0 / self._period.to_sec())
+        r = Rate(1.0 / self._period.to_sec(), reset=self._reset)
         current_expected = rospy.rostime.get_rostime() + self._period
         last_expected, last_real, last_duration = None, None, None
         while not rospy.core.is_shutdown() and not self._shutdown:
diff --git a/clients/rospy/src/rospy/topics.py b/clients/rospy/src/rospy/topics.py
index eb84b1f..b61a4ec 100644
--- a/clients/rospy/src/rospy/topics.py
+++ b/clients/rospy/src/rospy/topics.py
@@ -109,6 +109,10 @@ Message = genpy.Message
 # for interfacing with topics, while _TopicImpl implements the
 # underlying connection details. 
 
+if not hasattr(select, 'EPOLLRDHUP'):
+    select.EPOLLRDHUP = 0x2000
+
+
 class Topic(object):
     """Base class of L{Publisher} and L{Subscriber}"""
     
@@ -188,25 +192,28 @@ class Poller(object):
     on multiple platforms.  NOT thread-safe.
     """
     def __init__(self):
-        try:
+        if hasattr(select, 'epoll'):
+            self.poller = select.epoll()
+            self.add_fd = self.add_epoll
+            self.remove_fd = self.remove_epoll
+            self.error_iter = self.error_epoll_iter
+        elif hasattr(select, 'poll'):
             self.poller = select.poll()
             self.add_fd = self.add_poll
             self.remove_fd = self.remove_poll
             self.error_iter = self.error_poll_iter
-        except:
-            try:
-                # poll() not available, try kqueue
-                self.poller = select.kqueue()
-                self.add_fd = self.add_kqueue
-                self.remove_fd = self.remove_kqueue
-                self.error_iter = self.error_kqueue_iter
-                self.kevents = []
-            except:
-                #TODO: non-Noop impl for Windows
-                self.poller = self.noop
-                self.add_fd = self.noop
-                self.remove_fd = self.noop
-                self.error_iter = self.noop_iter
+        elif hasattr(select, 'kqueue'):
+            self.poller = select.kqueue()
+            self.add_fd = self.add_kqueue
+            self.remove_fd = self.remove_kqueue
+            self.error_iter = self.error_kqueue_iter
+            self.kevents = []
+        else:
+            #TODO: non-Noop impl for Windows
+            self.poller = self.noop
+            self.add_fd = self.noop
+            self.remove_fd = self.noop
+            self.error_iter = self.noop_iter
 
     def noop(self, *args):
         pass
@@ -228,6 +235,18 @@ class Poller(object):
             if event & (select.POLLHUP | select.POLLERR):
                 yield fd
 
+    def add_epoll(self, fd):
+        self.poller.register(fd, select.EPOLLHUP|select.EPOLLERR|select.EPOLLRDHUP)
+
+    def remove_epoll(self, fd):
+        self.poller.unregister(fd)
+
+    def error_epoll_iter(self):
+        events = self.poller.poll(0)
+        for fd, event in events:
+            if event & (select.EPOLLHUP | select.EPOLLERR | select.EPOLLRDHUP):
+                yield fd
+
     def add_kqueue(self, fd):
         self.kevents.append(select.kevent(fd))
 
@@ -439,6 +458,17 @@ class _TopicImpl(object):
             
             return True
 
+    def check(self):
+        fds_to_remove = list(self.connection_poll.error_iter())
+        if fds_to_remove:
+            with self.c_lock:
+                new_connections = self.connections[:]
+                to_remove = [x for x in new_connections if x.fileno() in fds_to_remove]
+                for x in to_remove:
+                    rospydebug("removing connection to %s, connection error detected"%(x.endpoint_id))
+                    self._remove_connection(new_connections, x)
+                self.connections = new_connections
+
     def remove_connection(self, c):
         """
         Remove connection from topic.
@@ -1136,6 +1166,15 @@ class _TopicManager(object):
                 t.close()
             self.pubs.clear()
             self.subs.clear()        
+
+            
+    def check_all(self):
+        """
+        Check all registered publication and subscriptions.
+        """
+        with self.lock:
+            for t in chain(iter(self.pubs.values()), iter(self.subs.values())):
+                t.check()
         
     def _add(self, ps, rmap, reg_type):
         """
diff --git a/ros_comm/CHANGELOG.rst b/ros_comm/CHANGELOG.rst
index e861184..98a3b14 100644
--- a/ros_comm/CHANGELOG.rst
+++ b/ros_comm/CHANGELOG.rst
@@ -2,6 +2,15 @@
 Changelog for package ros_comm
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
+1.13.1 (2017-07-27)
+-------------------
+
+1.13.0 (2017-02-22)
+-------------------
+
+1.12.7 (2017-02-17)
+-------------------
+
 1.12.6 (2016-10-26)
 -------------------
 
diff --git a/ros_comm/package.xml b/ros_comm/package.xml
index fc9d10e..ee08916 100644
--- a/ros_comm/package.xml
+++ b/ros_comm/package.xml
@@ -1,6 +1,6 @@
 <package>
   <name>ros_comm</name>
-  <version>1.12.6</version>
+  <version>1.13.1</version>
   <description>
     ROS communications-related packages, including core client libraries (roscpp, rospy) and graph introspection tools (rostopic, rosnode, rosservice, rosparam).
   </description>
diff --git a/test/test_rosbag/bag_migration_tests/CMakeLists.txt b/test/test_rosbag/bag_migration_tests/CMakeLists.txt
index 687b080..e33bd5d 100644
--- a/test/test_rosbag/bag_migration_tests/CMakeLists.txt
+++ b/test/test_rosbag/bag_migration_tests/CMakeLists.txt
@@ -5,22 +5,46 @@
 # generate_messages() it might make it work, or we can migrate the bag
 # files themselves.
 
-add_message_files(
-  DIRECTORY msg_current
-  FILES
-  Constants.msg
+set(MSG_DIRECTORY "msg_current" CACHE STRING "Messages directory")
+message(STATUS "Building messages in: ${MSG_DIRECTORY}")
+
+set(messages_common
   Converged.msg
   MigratedAddSub.msg
   MigratedExplicit.msg
   MigratedImplicit.msg
   MigratedMixed.msg
   PartiallyMigrated.msg
-  Renamed4.msg
   Simple.msg
   SimpleMigrated.msg
   SubUnmigrated.msg
-  Unmigrated.msg
-)
+  Unmigrated.msg)
+
+set(messages_msg_gen1
+  Constants.msg
+  Convergent.msg
+  Renamed1.msg)
+
+set(messages_msg_gen2
+  Constants.msg
+  Convergent.msg
+  Renamed2.msg)
+
+set(messages_msg_gen3
+  Renamed3.msg)
+
+set(messages_msg_gen4
+  Constants.msg
+  Renamed4.msg)
+
+set(messages_msg_current
+  Constants.msg
+  Renamed5.msg)
+
+add_message_files(
+  DIRECTORY ${MSG_DIRECTORY}
+  FILES ${messages_common} ${messages_${MSG_DIRECTORY}})
+
 generate_messages(DEPENDENCIES rosgraph_msgs std_msgs)
 
 catkin_download_test_data(download_data_test_constants_gen1.bag http://download.ros.org/data/test_rosbag/constants_gen1.bag FILENAME test/constants_gen1.bag MD5 77ec8cb20e823ee3f3a87d07ea1132df )
@@ -28,24 +52,30 @@ catkin_download_test_data(download_data_test_constants_gen2.bag http://download.
 catkin_download_test_data(download_data_test_converged_gen1.bag http://download.ros.org/data/test_rosbag/converged_gen1.bag FILENAME test/converged_gen1.bag MD5 8e3524157d31b5761ac951fe16e03e12 )
 catkin_download_test_data(download_data_test_converged_gen2.bag http://download.ros.org/data/test_rosbag/converged_gen2.bag FILENAME test/converged_gen2.bag MD5 0ad4041d2e3bab8262c12020ec3e048e )
 catkin_download_test_data(download_data_test_converged_gen3.bag http://download.ros.org/data/test_rosbag/converged_gen3.bag FILENAME test/converged_gen3.bag MD5 90dd16cea5c51fca65be617654fb6b76 )
+catkin_download_test_data(download_data_test_converged_gen4.bag http://download.ros.org/data/test_rosbag/converged_gen4.bag FILENAME test/converged_gen4.bag MD5 c88ac1f4a9a5eebd667ec55224988e40 )
 catkin_download_test_data(download_data_test_convergent_gen1.bag http://download.ros.org/data/test_rosbag/convergent_gen1.bag FILENAME test/convergent_gen1.bag MD5 a840aec95e50f3c828841b688dfab5a2 )
 catkin_download_test_data(download_data_test_convergent_gen2.bag http://download.ros.org/data/test_rosbag/convergent_gen2.bag FILENAME test/convergent_gen2.bag MD5 fd84c135ba1548985b870d0d5f4113e9 )
 catkin_download_test_data(download_data_test_migrated_addsub_gen1.bag http://download.ros.org/data/test_rosbag/migrated_addsub_gen1.bag FILENAME test/migrated_addsub_gen1.bag MD5 462e98cef72b5df56ce3feea9ddfc4d2 )
 catkin_download_test_data(download_data_test_migrated_explicit_gen1.bag http://download.ros.org/data/test_rosbag/migrated_explicit_gen1.bag FILENAME test/migrated_explicit_gen1.bag MD5 0b77e45aec3ddb19a9f9771c945e2615 )
 catkin_download_test_data(download_data_test_migrated_explicit_gen2.bag http://download.ros.org/data/test_rosbag/migrated_explicit_gen2.bag FILENAME test/migrated_explicit_gen2.bag MD5 b237680d6aae1b20355af097cf0f072b )
 catkin_download_test_data(download_data_test_migrated_explicit_gen3.bag http://download.ros.org/data/test_rosbag/migrated_explicit_gen3.bag FILENAME test/migrated_explicit_gen3.bag MD5 8b883286e23779bbfc30b0e5588a4d64 )
+catkin_download_test_data(download_data_test_migrated_explicit_gen4.bag http://download.ros.org/data/test_rosbag/migrated_explicit_gen4.bag FILENAME test/migrated_explicit_gen4.bag MD5 96a92282f16c30bac237870f144bf9f0 )
 catkin_download_test_data(download_data_test_migrated_implicit_gen1.bag http://download.ros.org/data/test_rosbag/migrated_implicit_gen1.bag FILENAME test/migrated_implicit_gen1.bag MD5 229d6cbd7dcec5e87fb2cf597b837243 )
 catkin_download_test_data(download_data_test_migrated_implicit_gen2.bag http://download.ros.org/data/test_rosbag/migrated_implicit_gen2.bag FILENAME test/migrated_implicit_gen2.bag MD5 df60111e5f8034ba6259c4d76d07339b )
 catkin_download_test_data(download_data_test_migrated_implicit_gen3.bag http://download.ros.org/data/test_rosbag/migrated_implicit_gen3.bag FILENAME test/migrated_implicit_gen3.bag MD5 d86f131070822f1673f7644bc28bfccd )
+catkin_download_test_data(download_data_test_migrated_implicit_gen4.bag http://download.ros.org/data/test_rosbag/migrated_implicit_gen4.bag FILENAME test/migrated_implicit_gen4.bag MD5 1d2cdb322996a8f1f4ee6359bded8700 )
 catkin_download_test_data(download_data_test_migrated_mixed_gen1.bag http://download.ros.org/data/test_rosbag/migrated_mixed_gen1.bag FILENAME test/migrated_mixed_gen1.bag MD5 2d0be37de2df6940b7bd93561dde7b51 )
 catkin_download_test_data(download_data_test_migrated_mixed_gen2.bag http://download.ros.org/data/test_rosbag/migrated_mixed_gen2.bag FILENAME test/migrated_mixed_gen2.bag MD5 e000b2de3e4c417b0c9fbba9d2e92dc4 )
 catkin_download_test_data(download_data_test_migrated_mixed_gen3.bag http://download.ros.org/data/test_rosbag/migrated_mixed_gen3.bag FILENAME test/migrated_mixed_gen3.bag MD5 6e1cbb529b7a45386589d00bf3908bdf )
+catkin_download_test_data(download_data_test_migrated_mixed_gen4.bag http://download.ros.org/data/test_rosbag/migrated_mixed_gen4.bag FILENAME test/migrated_mixed_gen4.bag MD5 fdbe1928646408c51ec9dc975dd5e678 )
 catkin_download_test_data(download_data_test_partially_migrated_gen1.bag http://download.ros.org/data/test_rosbag/partially_migrated_gen1.bag FILENAME test/partially_migrated_gen1.bag MD5 dcfcf1e1c1f7ddc5ab723e171273a385 )
 catkin_download_test_data(download_data_test_partially_migrated_gen2.bag http://download.ros.org/data/test_rosbag/partially_migrated_gen2.bag FILENAME test/partially_migrated_gen2.bag MD5 7b2d752559a7e3c724d8b2a032daf3c1 )
 catkin_download_test_data(download_data_test_partially_migrated_gen3.bag http://download.ros.org/data/test_rosbag/partially_migrated_gen3.bag FILENAME test/partially_migrated_gen3.bag MD5 01161f84591bf956df7dff0a5e3fd2db )
+catkin_download_test_data(download_data_test_partially_migrated_gen4.bag http://download.ros.org/data/test_rosbag/partially_migrated_gen4.bag FILENAME test/partially_migrated_gen4.bag MD5 38650a5e81b58500144646f8f781eb6b )
 catkin_download_test_data(download_data_test_renamed_gen1.bag http://download.ros.org/data/test_rosbag/renamed_gen1.bag FILENAME test/renamed_gen1.bag MD5 243d6109f3bfd2ad1af1337a776970e5 )
 catkin_download_test_data(download_data_test_renamed_gen2.bag http://download.ros.org/data/test_rosbag/renamed_gen2.bag FILENAME test/renamed_gen2.bag MD5 229c79262e42b71f36e316ab1d1ad943 )
 catkin_download_test_data(download_data_test_renamed_gen3.bag http://download.ros.org/data/test_rosbag/renamed_gen3.bag FILENAME test/renamed_gen3.bag MD5 c9c3d03807de367b533f5e0384b4d134 )
+catkin_download_test_data(download_data_test_renamed_gen4.bag http://download.ros.org/data/test_rosbag/renamed_gen4.bag FILENAME test/renamed_gen4.bag MD5 94454a67e7fb7187b61d46bc42f00b18 )
 catkin_download_test_data(download_data_test_subunmigrated_gen1.bag http://download.ros.org/data/test_rosbag/subunmigrated_gen1.bag FILENAME test/subunmigrated_gen1.bag MD5 c78b85016aa34669e36d1eb5a7b5f2c7 )
 catkin_download_test_data(download_data_test_unmigrated_gen1.bag http://download.ros.org/data/test_rosbag/unmigrated_gen1.bag FILENAME test/unmigrated_gen1.bag MD5 87d8d3a1c9679609533803709d21cea2 )
 
diff --git a/test/test_rosbag/bag_migration_tests/MessageHistory.txt b/test/test_rosbag/bag_migration_tests/MessageHistory.txt
index f96c3a6..ffb36c4 100644
--- a/test/test_rosbag/bag_migration_tests/MessageHistory.txt
+++ b/test/test_rosbag/bag_migration_tests/MessageHistory.txt
@@ -8,8 +8,8 @@ previous generation forward.
 
 To use a particular generation script, move msgs_N to msgs, and then
 run script/generate_data_N.py.  The bash script "generate_data" does
-this for all generations.  The helper scripts, "gen1, gen2, gen3, and
-current" switch the message context to that particular 
+this for all generations.  The helper scripts, "gen1, gen2, gen3, gen4,
+and current" switch the message context to that particular
 
 
 GENERATION 1:
@@ -24,15 +24,15 @@ GENERATION 1:
  Converged.msg
  Hierarchical.msg
  SuperHierarchical.msg
- 
+
 
 GENERATION 2:
  Unmigrated.msg
  Subunmigrated.msg
- PartiallyMigrated.msg - implicit 
- MigratedExplicit.msg  - explicit 
- MigratedImplicit.msg  - implicit 
- MigratedMixed.msg     - implicit 
+ PartiallyMigrated.msg - implicit
+ MigratedExplicit.msg  - explicit
+ MigratedImplicit.msg  - implicit
+ MigratedMixed.msg     - implicit
  Converged.msg         - Rename from Convergent.msg
  Renamed2.msg          - Rename from Renamed1.msg
  Hierarchical.msg
@@ -41,25 +41,37 @@ GENERATION 2:
 GENERATION 3
  Unmigrated.msg
  Subunmigrated.msg
- PartiallyMigrated.msg - explicit 
- MigratedExplicit.msg  - explicit 
- MigratedImplicit.msg  - implicit 
- MigratedMixed.msg     - explicit 
- Converged.msg         - explicit 
- Renamed3.msg          - rename from Renamed2.msg and explicit 
- Hierarchical.msg      - explicit 
+ PartiallyMigrated.msg - explicit
+ MigratedExplicit.msg  - explicit
+ MigratedImplicit.msg  - implicit
+ MigratedMixed.msg     - explicit
+ Converged.msg         - explicit
+ Renamed3.msg          - rename from Renamed2.msg and explicit
+ Hierarchical.msg      - explicit
  SuperHierarchical.msg - implicit
 
-CURRENT:
+GENERATION 4:
  UnMigrated.msg        - explicit  (No corresponding rule)
  Subunmigrated.msg
  PartiallyMigrated.msg - explicit  (No corresponding rule)
- MigratedExplicit.msg  - explicit 
- MigratedImplicit.msg  - implicit 
- MigratedMixed.msg     - implicit 
- Converged.msg         - implicit 
+ MigratedExplicit.msg  - explicit
+ MigratedImplicit.msg  - implicit
+ MigratedMixed.msg     - implicit
+ Converged.msg         - implicit
  Renamed4.msg          - rename from Renamed3.msg
- Hierarchical.msg      - implicit 
+ Hierarchical.msg      - implicit
  SuperHierarchical.msg
 
- 
+CURRENT:
+ UnMigrated.msg        - explicit  (No corresponding rule)
+ Subunmigrated.msg
+ PartiallyMigrated.msg - explicit  (No corresponding rule)
+ MigratedExplicit.msg  - explicit
+ MigratedImplicit.msg  - implicit
+ MigratedMixed.msg     - implicit
+ Converged.msg         - implicit
+ Renamed5.msg          - rename from Renamed4.msg
+ Hierarchical.msg      - implicit
+ SuperHierarchical.msg
+
+
diff --git a/test/test_rosbag/bag_migration_tests/README.md b/test/test_rosbag/bag_migration_tests/README.md
new file mode 100644
index 0000000..4b70a54
--- /dev/null
+++ b/test/test_rosbag/bag_migration_tests/README.md
@@ -0,0 +1,349 @@
+# Bag migration tests scripts
+
+In order to generate the data and rules for bag migration tests, two scripts are provided:
+
+ * **generate_data** : Generates *.bag* files with messages (data) to run the bag migration tests. 
+ * **generate_rules** : Help in the process of creating rules between two message generations.
+
+The next sections explain how to use these scripts in detail. The rest are auxiliary scripts that should NOT be used directly.
+
+Before running any of these scripts you need to build the **test_rosbag** package at least once in your workspace and `source` the environment workspace setup file. This can be done running the following from the root of the workspace:
+
+``` bash
+$ catkin_make_isolated
+$ source devel_isolated/test_rosbag/setup.bash
+```
+
+:warning: Since we use `catkin_make_isolated` in the scripts to build the different message generations, remember the scripts need to be run from the root of the workspace.
+
+## Generate Data
+
+The **generate_data** script generates *.bag* data files for one or multiple messsage generations. The output directory is the **bag_migration_tests/test** folder inside the **test_rosbag** package. It's the user responsability to move the output *.bag* files to an HTTP server and download them from the **CMakeLists.txt** file as in this example:
+
+``` cmake
+catkin_download_test_data(download_data_test_constants_gen1.bag http://download.ros.org/data/test_rosbag/constants_gen1.bag FILENAME test/constants_gen1.bag MD5 77ec8cb20e823ee3f3a87d07ea1132df )
+```
+
+Currently, there are the following message generations on the **test_rosbag** package, under the **bag_migration_tests** folder, in these sub-folders:
+
+* **msg_gen1** : Message generation \#1.
+* **msg_gen2** : Message generation \#2.
+* **msg_gen3** : Message generation \#3.
+* **msg_current** : Current message generation.
+
+:warning: Note the **generate_data** script doesn't generate data for the **msg_current** generation because we don't have to. This is because the current generation is never the source of any migration rules, just the target for the latest generation.
+
+This script takes the following positional arguments:
+
+* **generations** : ID of the messages generations to build and generate *.bag* data files for. It defaults to `1 2 3`.
+
+### Examples
+
+1. Generate data for the message generation \#1:
+
+``` bash
+$ rosrun test_rosbag generate_data 1
+Generating data in '/home/eperdomo/dev/ws/clearpath_ws/src/ros_comm/test/test_rosbag/bag_migration_tests' for generation: 1
+```
+
+This will create the following *.bag* files inside the **test_rosbag** package:
+
+``` bash
+bag_migration_tests/test/constants_gen1.bag
+bag_migration_tests/test/converged_gen1.bag
+bag_migration_tests/test/convergent_gen1.bag
+bag_migration_tests/test/migrated_addsub_gen1.bag
+bag_migration_tests/test/migrated_explicit_gen1.bag
+bag_migration_tests/test/migrated_implicit_gen1.bag
+bag_migration_tests/test/migrated_mixed_gen1.bag
+bag_migration_tests/test/partially_migrated_gen1.bag
+bag_migration_tests/test/renamed_gen1.bag
+bag_migration_tests/test/subunmigrated_gen1.bag
+bag_migration_tests/test/unmigrated_gen1.bag
+```
+
+Each of these bag files have a single message of the generation requested, as shown below with `rosbag info`:
+
+``` bash
+$ rosbag info $(rospack find test_rosbag)/bag_migration_tests/test/constants_gen1.bag
+path:        /home/eperdomo/dev/ws/clearpath_ws/src/ros_comm/test/test_rosbag/bag_migration_tests/test/constants_gen1.bag
+version:     2.0
+duration:    0.0s
+start:       Dec 31 1969 19:00:00.00 (0.00)
+end:         Dec 31 1969 19:00:00.00 (0.00)
+size:        4.7 KB
+messages:    1
+compression: none [1/1 chunks]
+types:       test_rosbag/Constants [06a34bda7d4ea2950ab952e89ca35d7a]
+topics:      constants   1 msg     : test_rosbag/Constants
+```
+
+2. Generate data for the message generations \#2 and \#3:
+
+``` bash
+$ rosrun test_rosbag generate_data 2 3
+Generating data in '/home/eperdomo/dev/ws/clearpath_ws/src/ros_comm/test/test_rosbag/bag_migration_tests' for generation: 2
+Generating data in '/home/eperdomo/dev/ws/clearpath_ws/src/ros_comm/test/test_rosbag/bag_migration_tests' for generation: 3
+```
+
+This will create the following *.bag* files inside the **test_rosbag** package:
+
+``` bash
+bag_migration_tests/test/constants_gen2.bag
+bag_migration_tests/test/converged_gen2.bag
+bag_migration_tests/test/converged_gen3.bag
+bag_migration_tests/test/convergent_gen2.bag
+bag_migration_tests/test/migrated_explicit_gen2.bag
+bag_migration_tests/test/migrated_explicit_gen3.bag
+bag_migration_tests/test/migrated_implicit_gen2.bag
+bag_migration_tests/test/migrated_implicit_gen3.bag
+bag_migration_tests/test/migrated_mixed_gen2.bag
+bag_migration_tests/test/migrated_mixed_gen3.bag
+bag_migration_tests/test/partially_migrated_gen2.bag
+bag_migration_tests/test/partially_migrated_gen3.bag
+bag_migration_tests/test/renamed_gen2.bag
+bag_migration_tests/test/renamed_gen3.bag
+```
+
+3. Generate data for all the message generations, relying on the default value for the argument:
+
+``` bash
+$ rosrun test_rosbag generate_data
+Generating data in '/home/eperdomo/dev/ws/clearpath_ws/src/ros_comm/test/test_rosbag/bag_migration_tests' for generation: 1
+Generating data in '/home/eperdomo/dev/ws/clearpath_ws/src/ros_comm/test/test_rosbag/bag_migration_tests' for generation: 2
+Generating data in '/home/eperdomo/dev/ws/clearpath_ws/src/ros_comm/test/test_rosbag/bag_migration_tests' for generation: 3
+```
+
+This will create the following *.bag* files inside the **test_rosbag** package:
+
+``` bash
+bag_migration_tests/test/constants_gen1.bag
+bag_migration_tests/test/constants_gen2.bag
+bag_migration_tests/test/converged_gen1.bag
+bag_migration_tests/test/converged_gen2.bag
+bag_migration_tests/test/converged_gen3.bag
+bag_migration_tests/test/convergent_gen1.bag
+bag_migration_tests/test/convergent_gen2.bag
+bag_migration_tests/test/migrated_addsub_gen1.bag
+bag_migration_tests/test/migrated_explicit_gen1.bag
+bag_migration_tests/test/migrated_explicit_gen2.bag
+bag_migration_tests/test/migrated_explicit_gen3.bag
+bag_migration_tests/test/migrated_implicit_gen1.bag
+bag_migration_tests/test/migrated_implicit_gen2.bag
+bag_migration_tests/test/migrated_implicit_gen3.bag
+bag_migration_tests/test/migrated_mixed_gen1.bag
+bag_migration_tests/test/migrated_mixed_gen2.bag
+bag_migration_tests/test/migrated_mixed_gen3.bag
+bag_migration_tests/test/partially_migrated_gen1.bag
+bag_migration_tests/test/partially_migrated_gen2.bag
+bag_migration_tests/test/partially_migrated_gen3.bag
+bag_migration_tests/test/renamed_gen1.bag
+bag_migration_tests/test/renamed_gen2.bag
+bag_migration_tests/test/renamed_gen3.bag
+bag_migration_tests/test/subunmigrated_gen1.bag
+bag_migration_tests/test/unmigrated_gen1.bag
+```
+
+## Generate Rules
+
+The **generate_rules** script helps in the process of creating migration rules from one message generation to another. The scripts requires the user input every time a rule is created, since the rule **update** method needs to be implemented and the rule needs to be set to **valid = True**. It also needs the user to tell the new name for moved/renamed messages. The user can also decide to completely remove the rule if the intention is to test what happens when rules are missed.
+
+For convenience, the script loads all the migration rules (*.bmr* files) already available on the **msg_** and **test** sub-folders, under the **bag_migration_tests** folder in the **test_rosbag** package.
+
+This script takes the following positional arguments:
+
+* **source** : Source message generation.
+* **target** : Target message generation.
+
+The message generation can be any of the following: `gen1`, `gen2`, `gen3` or `current`. That is, the suffix of all the message generations available in the **test_rosbag** package, under the **bag_migration_tests** folder, with the **msg_** prefix.
+
+The output folder for the generated rules is the folder for the **source** message generation, e.g. **msg_gen1** for `gen1`.
+
+The script proceeds as follows:
+
+1. Builds the **source** message generation.
+2. Save the **source** full text message definition for all messages in this generation.
+3. Builds the **target** message generation.
+4. Creates all migration rules needed from **source** to **target** and prompts the user to implement them (or remove if not needed).
+
+:warning: The migration rules needs to be organized after, since they can have misleading filenames.
+
+### Examples
+
+1. Generate migration rules from the generation \#1 to \#2 from scratch:
+
+Since the **generate_rules** scripts loads the existing rules in the **test** sub-folder, we need to remove or rename them first:
+
+``` bash
+$ roscd test_rosbag/bag_migration_tests/test
+$ ls *.bmr | xargs -I f mv f f.bak
+$ cd -
+```
+
+Now we can generate the rules from scratch, without any other rules interfering with the new ones:
+
+``` bash
+$ rosrun test_rosbag generate_rules gen1 gen2
+Building generation: gen1
+
+Saving messages full text for generation: gen1
+Saved message test_rosbag/SimpleMigrated: msg_gen1/SimpleMigrated.saved
+Saved message test_rosbag/SubUnmigrated: msg_gen1/SubUnmigrated.saved
+Saved message test_rosbag/Convergent: msg_gen1/Convergent.saved
+Saved message test_rosbag/Unmigrated: msg_gen1/Unmigrated.saved
+Saved message test_rosbag/MigratedImplicit: msg_gen1/MigratedImplicit.saved
+Saved message test_rosbag/PartiallyMigrated: msg_gen1/PartiallyMigrated.saved
+Saved message test_rosbag/Constants: msg_gen1/Constants.saved
+Saved message test_rosbag/MigratedExplicit: msg_gen1/MigratedExplicit.saved
+Saved message test_rosbag/Converged: msg_gen1/Converged.saved
+Saved message test_rosbag/Simple: msg_gen1/Simple.saved
+Saved message test_rosbag/MigratedMixed: msg_gen1/MigratedMixed.saved
+Saved message test_rosbag/Renamed1: msg_gen1/Renamed1.saved
+Saved message test_rosbag/MigratedAddSub: msg_gen1/MigratedAddSub.saved
+
+Building generation: gen2
+
+Making rules from source generation 'gen1' to target generation 'gen2'
+WARNING: Within rule [GENERATED.update_test_rosbag_MigratedImplicit_e809c9d02226cf20287aad007a48a177] cannot migrate from subtype [MigratedExplicit] to [MigratedExplicit]..
+The following migrations need to occur:
+ * From: test_rosbag/MigratedImplicit [e809c9d02226cf20287aad007a48a177]
+   To:   test_rosbag/MigratedImplicit [24b6ff9552f4ef454cf6b71bd64da259]
+    1 rules missing:
+     * From: test_rosbag/MigratedExplicit [c7936d50a749a1f589d6fc81eae24b34]
+       To:   test_rosbag/MigratedExplicit [fa072fb3cfcf105e1e5609a7467e2a14]
+
+The necessary rule files have been written to: msg_gen1/MigratedImplicit.bmr
+Created rule for msg_gen1/MigratedImplicit.saved: msg_gen1/MigratedImplicit.bmr
+Set valid = True, the order and implement the update method, or remove it if you don't want it.
+Then press ENTER.
+
+The following migrations need to occur:
+ * From: test_rosbag/MigratedExplicit [c7936d50a749a1f589d6fc81eae24b34]
+   To:   test_rosbag/MigratedExplicit [fa072fb3cfcf105e1e5609a7467e2a14]
+
+No additional rule files needed to be generated.  msg_gen1/MigratedExplicit.bmr not created.
+No rule needed for msg_gen1/MigratedExplicit.saved!
+The following migrations need to occur:
+ * From: test_rosbag/PartiallyMigrated [44a0fba96e9fa39d652ea664fc598253]
+   To:   test_rosbag/PartiallyMigrated [e6d73341e7b3f15f987c0cf194f97350]
+
+No additional rule files needed to be generated.  msg_gen1/PartiallyMigrated.bmr not created.
+No rule needed for msg_gen1/PartiallyMigrated.saved!
+Saved definition is up to date.
+No rule needed for msg_gen1/SubUnmigrated.saved!
+The following migrations need to occur:
+ * From: test_rosbag/Renamed1 [2fbee7c2602a76620804dfad673383b9]
+   To:   Unknown
+    1 rules missing:
+     * From: test_rosbag/Renamed1 [2fbee7c2602a76620804dfad673383b9]
+       To:   Unknown
+The message type test_rosbag/Renamed1 appears to have moved.  Please enter the type to migrate it to.
+>test_rosbag/Renamed2
+Creating the migration rule for test_rosbag/Renamed2 requires additional missing rules:
+
+The necessary rule files have been written to: msg_gen1/Renamed1.bmr
+Created rule for msg_gen1/Renamed1.saved: msg_gen1/Renamed1.bmr
+Set valid = True, the order and implement the update method, or remove it if you don't want it.
+Then press ENTER.
+
+The following migrations need to occur:
+ * From: test_rosbag/MigratedMixed [4517becf622c1e131ed4f7bfc3d5d093]
+   To:   test_rosbag/MigratedMixed [5568494133a082ad58ef1aa391f47e2b]
+
+No additional rule files needed to be generated.  msg_gen1/MigratedMixed.bmr not created.
+No rule needed for msg_gen1/MigratedMixed.saved!
+Saved definition is up to date.
+No rule needed for msg_gen1/Simple.saved!
+The following migrations need to occur:
+ * From: test_rosbag/SimpleMigrated [f3d103d10e4d7f4e5c4b19aa46d9a9dd]
+   To:   test_rosbag/SimpleMigrated [01dfc3630b3a6d483b2f36047889c82c]
+    1 rules missing:
+     * From: test_rosbag/SimpleMigrated [f3d103d10e4d7f4e5c4b19aa46d9a9dd]
+       To:   test_rosbag/SimpleMigrated [01dfc3630b3a6d483b2f36047889c82c]
+
+The necessary rule files have been written to: msg_gen1/SimpleMigrated.bmr
+Created rule for msg_gen1/SimpleMigrated.saved: msg_gen1/SimpleMigrated.bmr
+Set valid = True, the order and implement the update method, or remove it if you don't want it.
+Then press ENTER.
+
+The following migrations need to occur:
+ * From: test_rosbag/Convergent [60346ca10167913d79a124d3920677c6]
+   To:   test_rosbag/Convergent [fadc2231052dc3e2ecb5a84eea7e1e2d]
+
+No additional rule files needed to be generated.  msg_gen1/Convergent.bmr not created.
+No rule needed for msg_gen1/Convergent.saved!
+The following migrations need to occur:
+ * From: test_rosbag/MigratedAddSub [c5d68a52143661d05909248952fc11f1]
+   To:   test_rosbag/MigratedAddSub [f54ff3b9ba622359fa96ac15d4498153]
+    1 rules missing:
+     * From: test_rosbag/MigratedAddSub [c5d68a52143661d05909248952fc11f1]
+       To:   test_rosbag/MigratedAddSub [f54ff3b9ba622359fa96ac15d4498153]
+
+The necessary rule files have been written to: msg_gen1/MigratedAddSub.bmr
+Created rule for msg_gen1/MigratedAddSub.saved: msg_gen1/MigratedAddSub.bmr
+Set valid = True, the order and implement the update method, or remove it if you don't want it.
+Then press ENTER.
+
+Saved definition is up to date.
+No rule needed for msg_gen1/Unmigrated.saved!
+The following migrations need to occur:
+ * From: test_rosbag/Converged [13459e473cfc2d719fd495bd7a0b747b]
+   To:   test_rosbag/Converged [a47f409894343606276bb95cd2fd6b12]
+
+No additional rule files needed to be generated.  msg_gen1/Converged.bmr not created.
+No rule needed for msg_gen1/Converged.saved!
+The following migrations need to occur:
+ * From: test_rosbag/Constants [06a34bda7d4ea2950ab952e89ca35d7a]
+   To:   test_rosbag/Constants [ae89f5ac418be503530c99f2c7907db7]
+    1 rules missing:
+     * From: test_rosbag/Constants [06a34bda7d4ea2950ab952e89ca35d7a]
+       To:   test_rosbag/Constants [ae89f5ac418be503530c99f2c7907db7]
+
+The necessary rule files have been written to: msg_gen1/Constants.bmr
+Created rule for msg_gen1/Constants.saved: msg_gen1/Constants.bmr
+Set valid = True, the order and implement the update method, or remove it if you don't want it.
+Then press ENTER.
+
+* Remember that migration rules for renamed messages needs to be created manually!
+* Also remember that the migration rules in the files generated by this script might belong to other messages,
+  other than the one on the file name, so you should organize them properly!
+```
+
+This will create the following *.saved* full text message definitions on the **source** folder, i.e. **msg_gen1**:
+
+``` bash
+bag_migration_tests/msg_gen1/Constants.saved
+bag_migration_tests/msg_gen1/Converged.saved
+bag_migration_tests/msg_gen1/Convergent.saved
+bag_migration_tests/msg_gen1/MigratedAddSub.saved
+bag_migration_tests/msg_gen1/MigratedExplicit.saved
+bag_migration_tests/msg_gen1/MigratedImplicit.saved
+bag_migration_tests/msg_gen1/MigratedMixed.saved
+bag_migration_tests/msg_gen1/PartiallyMigrated.saved
+bag_migration_tests/msg_gen1/Renamed1.saved
+bag_migration_tests/msg_gen1/Simple.saved
+bag_migration_tests/msg_gen1/SimpleMigrated.saved
+bag_migration_tests/msg_gen1/SubUnmigrated.saved
+bag_migration_tests/msg_gen1/Unmigrated.saved
+```
+
+And will create the following *.bmr* migration rules, that the user need to implement and make valid as they are created:
+
+``` bash
+bag_migration_tests/msg_gen1/Constants.bmr
+bag_migration_tests/msg_gen1/MigratedAddSub.bmr
+bag_migration_tests/msg_gen1/MigratedImplicit.bmr
+bag_migration_tests/msg_gen1/Renamed1.bmr
+bag_migration_tests/msg_gen1/SimpleMigrated.bmr
+```
+2. Generate migration rules from the generation \#3 to the **current** one:
+
+This assumes we've previously create the rules from generation \#1 to \#2 and \#2 to \#3. With those rules created (from scratch), now we can create the ones from \#3 to the **current** generation with:
+
+``` bash
+$ rosrun test_rosbag generate_rules gen3 current
+```
+
+The output and process will be similar to the previous example.
+
+At the end, the user should organize all the rules from different generations. It's recommended to put all the rules for the same message in a single file. This file would have all the migration rules for it, for all the generations that need them.
diff --git a/test/test_rosbag/bag_migration_tests/current b/test/test_rosbag/bag_migration_tests/current
deleted file mode 100755
index 7693f3f..0000000
--- a/test/test_rosbag/bag_migration_tests/current
+++ /dev/null
@@ -1,6 +0,0 @@
-#!/bin/bash
-
-make clean-msg-only;
-rm -rf msg;
-cp -r msg_current msg;
-make
\ No newline at end of file
diff --git a/test/test_rosbag/bag_migration_tests/gen1 b/test/test_rosbag/bag_migration_tests/gen1
deleted file mode 100755
index 0789223..0000000
--- a/test/test_rosbag/bag_migration_tests/gen1
+++ /dev/null
@@ -1,6 +0,0 @@
-#!/bin/bash
-
-make clean-msg-only;
-rm -rf msg;
-cp -r msg_gen1 msg;
-make;
diff --git a/test/test_rosbag/bag_migration_tests/gen2 b/test/test_rosbag/bag_migration_tests/gen2
deleted file mode 100755
index 2ca3e87..0000000
--- a/test/test_rosbag/bag_migration_tests/gen2
+++ /dev/null
@@ -1,6 +0,0 @@
-#!/bin/bash
-
-make clean-msg-only;
-rm -rf msg;
-cp -r msg_gen2 msg;
-make;
\ No newline at end of file
diff --git a/test/test_rosbag/bag_migration_tests/gen3 b/test/test_rosbag/bag_migration_tests/gen3
deleted file mode 100755
index fb51f56..0000000
--- a/test/test_rosbag/bag_migration_tests/gen3
+++ /dev/null
@@ -1,6 +0,0 @@
-#!/bin/bash
-
-make clean-msg-only;
-rm -rf msg;
-cp -r msg_gen3 msg;
-make;
diff --git a/test/test_rosbag/bag_migration_tests/generate_data b/test/test_rosbag/bag_migration_tests/generate_data
deleted file mode 100755
index 4d8904e..0000000
--- a/test/test_rosbag/bag_migration_tests/generate_data
+++ /dev/null
@@ -1,24 +0,0 @@
-#!/bin/bash
-
-make clean-msg-only;
-rm -rf msg;
-cp -r msg_gen1 msg;
-make;
-./scripts/generate_data_1.py
-
-make clean-msg-only;
-rm -rf msg;
-cp -r msg_gen2 msg;
-make;
-./scripts/generate_data_2.py
-
-make clean-msg-only;
-rm -rf msg;
-cp -r msg_gen3 msg;
-make;
-./scripts/generate_data_3.py
-
-make clean-msg-only;
-rm -rf msg;
-cp -r msg_current msg;
-make
\ No newline at end of file
diff --git a/test/test_rosbag/bag_migration_tests/msg_current/MigratedExplicit.msg b/test/test_rosbag/bag_migration_tests/msg_current/MigratedExplicit.msg
index 516867e..56f0900 100644
--- a/test/test_rosbag/bag_migration_tests/msg_current/MigratedExplicit.msg
+++ b/test/test_rosbag/bag_migration_tests/msg_current/MigratedExplicit.msg
@@ -1,4 +1,4 @@
 Header  header
-float32 afield2 #58.2
+float32 field2 #58.2
 string  combo_field3 #"aldfkja 17"
-int32   afield4 #82
\ No newline at end of file
+int32   field4 #82
diff --git a/test/test_rosbag/bag_migration_tests/msg_current/MigratedImplicit.msg b/test/test_rosbag/bag_migration_tests/msg_current/MigratedImplicit.msg
index 9300978..a4658c5 100644
--- a/test/test_rosbag/bag_migration_tests/msg_current/MigratedImplicit.msg
+++ b/test/test_rosbag/bag_migration_tests/msg_current/MigratedImplicit.msg
@@ -1,5 +1,5 @@
 Header  header
-MigratedExplicit field4 #(17, 58.2 "aldfkja", 82)
+MigratedExplicit field4 #(58.2 "aldfkja 17", 82)
 string  field3 #"kljene"
 float32 field2 #16.32
 int32   field1 #34
diff --git a/test/test_rosbag/bag_migration_tests/msg_current/MigratedMixed.msg b/test/test_rosbag/bag_migration_tests/msg_current/MigratedMixed.msg
index a5020d1..d927783 100644
--- a/test/test_rosbag/bag_migration_tests/msg_current/MigratedMixed.msg
+++ b/test/test_rosbag/bag_migration_tests/msg_current/MigratedMixed.msg
@@ -1,3 +1,3 @@
 Header             header
-MigratedImplicit   field1 #(34, 16.32, "kjljene", (17, 58.2, "aldfkja", 82))
+MigratedImplicit   field1 #(34, 16.32, "kjljene", (58.2, "aldfkja 17", 82))
 int32              field2 #59
diff --git a/test/test_rosbag/bag_migration_tests/msg_current/PartiallyMigrated.msg b/test/test_rosbag/bag_migration_tests/msg_current/PartiallyMigrated.msg
index 4438f29..13b5a72 100644
--- a/test/test_rosbag/bag_migration_tests/msg_current/PartiallyMigrated.msg
+++ b/test/test_rosbag/bag_migration_tests/msg_current/PartiallyMigrated.msg
@@ -1,4 +1,5 @@
 int32            field1 # 40
-MigratedExplicit field2 # (17, 58.2, "aldfkja", 82)
+MigratedExplicit field2 # (58.2, "aldfkja 17", 82)
 string           field3 # "radasdk"
-float32          field5 # 63.4
+float32          field4 # 63.4
+float64          field5 # 123.4
diff --git a/test/test_rosbag/bag_migration_tests/msg_current/Renamed4.msg b/test/test_rosbag/bag_migration_tests/msg_current/Renamed5.msg
similarity index 100%
copy from test/test_rosbag/bag_migration_tests/msg_current/Renamed4.msg
copy to test/test_rosbag/bag_migration_tests/msg_current/Renamed5.msg
diff --git a/test/test_rosbag/bag_migration_tests/msg_current/Unmigrated.msg b/test/test_rosbag/bag_migration_tests/msg_current/Unmigrated.msg
index 09a451b..ef56eb3 100644
--- a/test/test_rosbag/bag_migration_tests/msg_current/Unmigrated.msg
+++ b/test/test_rosbag/bag_migration_tests/msg_current/Unmigrated.msg
@@ -1,3 +1,4 @@
 int32   field1 #12
 string  field2 #"uuiasjs"
-float32 field3 #61.7
\ No newline at end of file
+float32 field3 #61.7
+float64 field4 #123.4
\ No newline at end of file
diff --git a/test/test_rosbag/bag_migration_tests/msg_gen4/Constants.msg b/test/test_rosbag/bag_migration_tests/msg_gen4/Constants.msg
new file mode 100644
index 0000000..fa21f8f
--- /dev/null
+++ b/test/test_rosbag/bag_migration_tests/msg_gen4/Constants.msg
@@ -0,0 +1,3 @@
+int32 CONSTANT=2
+int32 CONSTANT_TWO=42
+int32 value
\ No newline at end of file
diff --git a/test/test_rosbag/bag_migration_tests/msg_gen4/Converged.msg b/test/test_rosbag/bag_migration_tests/msg_gen4/Converged.msg
new file mode 100644
index 0000000..c017d96
--- /dev/null
+++ b/test/test_rosbag/bag_migration_tests/msg_gen4/Converged.msg
@@ -0,0 +1,2 @@
+float32[4]           field1 # [1.2, 3.4, 5.6, 7.8]
+SimpleMigrated[4]    field2 # [11, 22, 33, 44]
\ No newline at end of file
diff --git a/test/test_rosbag/bag_migration_tests/msg_gen4/MigratedAddSub.msg b/test/test_rosbag/bag_migration_tests/msg_gen4/MigratedAddSub.msg
new file mode 100644
index 0000000..d45107b
--- /dev/null
+++ b/test/test_rosbag/bag_migration_tests/msg_gen4/MigratedAddSub.msg
@@ -0,0 +1,2 @@
+Simple field1
+Simple field2
\ No newline at end of file
diff --git a/test/test_rosbag/bag_migration_tests/msg_current/MigratedExplicit.msg b/test/test_rosbag/bag_migration_tests/msg_gen4/MigratedExplicit.msg
similarity index 100%
copy from test/test_rosbag/bag_migration_tests/msg_current/MigratedExplicit.msg
copy to test/test_rosbag/bag_migration_tests/msg_gen4/MigratedExplicit.msg
diff --git a/test/test_rosbag/bag_migration_tests/msg_current/MigratedImplicit.msg b/test/test_rosbag/bag_migration_tests/msg_gen4/MigratedImplicit.msg
similarity index 62%
copy from test/test_rosbag/bag_migration_tests/msg_current/MigratedImplicit.msg
copy to test/test_rosbag/bag_migration_tests/msg_gen4/MigratedImplicit.msg
index 9300978..a4658c5 100644
--- a/test/test_rosbag/bag_migration_tests/msg_current/MigratedImplicit.msg
+++ b/test/test_rosbag/bag_migration_tests/msg_gen4/MigratedImplicit.msg
@@ -1,5 +1,5 @@
 Header  header
-MigratedExplicit field4 #(17, 58.2 "aldfkja", 82)
+MigratedExplicit field4 #(58.2 "aldfkja 17", 82)
 string  field3 #"kljene"
 float32 field2 #16.32
 int32   field1 #34
diff --git a/test/test_rosbag/bag_migration_tests/msg_gen4/MigratedMixed.msg b/test/test_rosbag/bag_migration_tests/msg_gen4/MigratedMixed.msg
new file mode 100644
index 0000000..d927783
--- /dev/null
+++ b/test/test_rosbag/bag_migration_tests/msg_gen4/MigratedMixed.msg
@@ -0,0 +1,3 @@
+Header             header
+MigratedImplicit   field1 #(34, 16.32, "kjljene", (58.2, "aldfkja 17", 82))
+int32              field2 #59
diff --git a/test/test_rosbag/bag_migration_tests/msg_gen4/PartiallyMigrated.msg b/test/test_rosbag/bag_migration_tests/msg_gen4/PartiallyMigrated.msg
new file mode 100644
index 0000000..e25190d
--- /dev/null
+++ b/test/test_rosbag/bag_migration_tests/msg_gen4/PartiallyMigrated.msg
@@ -0,0 +1,4 @@
+int32            field1 # 40
+MigratedExplicit field2 # (58.2, "aldfkja 17", 82)
+string           field3 # "radasdk"
+float32          field4 # 63.4
diff --git a/test/test_rosbag/bag_migration_tests/msg_current/Renamed4.msg b/test/test_rosbag/bag_migration_tests/msg_gen4/Renamed4.msg
similarity index 100%
rename from test/test_rosbag/bag_migration_tests/msg_current/Renamed4.msg
rename to test/test_rosbag/bag_migration_tests/msg_gen4/Renamed4.msg
diff --git a/test/test_rosbag/bag_migration_tests/msg_gen4/Simple.msg b/test/test_rosbag/bag_migration_tests/msg_gen4/Simple.msg
new file mode 100644
index 0000000..a76c824
--- /dev/null
+++ b/test/test_rosbag/bag_migration_tests/msg_gen4/Simple.msg
@@ -0,0 +1 @@
+int32 field1 #42
\ No newline at end of file
diff --git a/test/test_rosbag/bag_migration_tests/msg_gen4/SimpleMigrated.msg b/test/test_rosbag/bag_migration_tests/msg_gen4/SimpleMigrated.msg
new file mode 100644
index 0000000..89ba8e1
--- /dev/null
+++ b/test/test_rosbag/bag_migration_tests/msg_gen4/SimpleMigrated.msg
@@ -0,0 +1 @@
+int32 data4 # 42
\ No newline at end of file
diff --git a/test/test_rosbag/bag_migration_tests/msg_gen4/SubUnmigrated.msg b/test/test_rosbag/bag_migration_tests/msg_gen4/SubUnmigrated.msg
new file mode 100644
index 0000000..5a2ee5d
--- /dev/null
+++ b/test/test_rosbag/bag_migration_tests/msg_gen4/SubUnmigrated.msg
@@ -0,0 +1,2 @@
+int32      field1 # 92
+Unmigrated field2 # (12, "uuiasjs", 61.7)
diff --git a/test/test_rosbag/bag_migration_tests/msg_current/Unmigrated.msg b/test/test_rosbag/bag_migration_tests/msg_gen4/Unmigrated.msg
similarity index 100%
copy from test/test_rosbag/bag_migration_tests/msg_current/Unmigrated.msg
copy to test/test_rosbag/bag_migration_tests/msg_gen4/Unmigrated.msg
diff --git a/test/test_rosbag/bag_migration_tests/scripts/generate_data b/test/test_rosbag/bag_migration_tests/scripts/generate_data
new file mode 100755
index 0000000..6fb9049
--- /dev/null
+++ b/test/test_rosbag/bag_migration_tests/scripts/generate_data
@@ -0,0 +1,67 @@
+#!/bin/bash
+
+# Function that builds a message generation:
+build_generation()
+{
+    catkin_make_isolated -q --pkg test_rosbag --cmake-args -DMSG_DIRECTORY="msg_$1" >/dev/null
+}
+
+# Function that saves all the message types in a bag file:
+save_msg()
+{
+    generation=${1/.bag}
+    generation=${generation/*_/}
+
+    msg_types=$(rosbag info -y -k types "$1" | grep type | awk '{print $3}')
+
+    for msg_type in $msg_types
+    do
+        saved_msg=${msg_type/test_rosbag\//}_${generation}.saved
+
+        rosrun rosbag savemsg.py -b "$1" "$msg_type" > "test/${saved_msg}"
+    done
+}
+
+# Take optional positional argument that specifies which message generations to build; defaults to $(seq 1 4):
+if [ $# -gt 0 ]
+then
+    GENERATIONS=$@
+else
+    GENERATIONS=$(seq 1 4)
+fi
+
+# Find the bag_migration_tests folder inside the test_rosbag package, since the .bag files would be
+# created in the test sub-folder:
+DESTINATION=$(rospack find test_rosbag)/bag_migration_tests
+
+# Generate data for each message generation:
+for GENERATION in ${GENERATIONS}
+do
+    echo "Generating data in '${DESTINATION}' for generation: ${GENERATION}"
+
+    # Build messages generation:
+    build_generation "gen${GENERATION}"
+
+    if [ $? -ne 0 ]
+    then
+        >&2 echo "Failed to build messages!"
+        continue
+    fi
+
+    # Generate data:
+    cd "${DESTINATION}"
+    rosrun test_rosbag "generate_data_${GENERATION}.py"
+    cd "$OLDPWD"
+
+    if [ $? -ne 0 ]
+    then
+        >&2 echo "Failed to generate data!"
+        continue
+    fi
+done
+
+# Build messages for the current generation:
+build_generation current
+
+# We don't really need to change the directory back to the old one, it's done automatically on exit:
+# cd $OLDPWD
diff --git a/test/test_rosbag/bag_migration_tests/scripts/generate_data_1.py b/test/test_rosbag/bag_migration_tests/scripts/generate_data_1.py
index 571b1d1..0016eb6 100755
--- a/test/test_rosbag/bag_migration_tests/scripts/generate_data_1.py
+++ b/test/test_rosbag/bag_migration_tests/scripts/generate_data_1.py
@@ -32,7 +32,6 @@
 # POSSIBILITY OF SUCH DAMAGE.
 #
 
-import rospy
 from test_rosbag.msg import *
 
 import genpy
diff --git a/test/test_rosbag/bag_migration_tests/scripts/generate_data_2.py b/test/test_rosbag/bag_migration_tests/scripts/generate_data_2.py
index efeca45..807aad0 100755
--- a/test/test_rosbag/bag_migration_tests/scripts/generate_data_2.py
+++ b/test/test_rosbag/bag_migration_tests/scripts/generate_data_2.py
@@ -32,7 +32,6 @@
 # POSSIBILITY OF SUCH DAMAGE.
 #
 
-import rospy
 from test_rosbag.msg import *
 
 import genpy
diff --git a/test/test_rosbag/bag_migration_tests/scripts/generate_data_3.py b/test/test_rosbag/bag_migration_tests/scripts/generate_data_3.py
index b359384..2784ed5 100755
--- a/test/test_rosbag/bag_migration_tests/scripts/generate_data_3.py
+++ b/test/test_rosbag/bag_migration_tests/scripts/generate_data_3.py
@@ -31,7 +31,6 @@
 # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 # POSSIBILITY OF SUCH DAMAGE.
 
-import rospy
 from test_rosbag.msg import *
 
 import rosbag
diff --git a/test/test_rosbag/bag_migration_tests/scripts/generate_data_3.py b/test/test_rosbag/bag_migration_tests/scripts/generate_data_4.py
similarity index 76%
copy from test/test_rosbag/bag_migration_tests/scripts/generate_data_3.py
copy to test/test_rosbag/bag_migration_tests/scripts/generate_data_4.py
index b359384..658279f 100755
--- a/test/test_rosbag/bag_migration_tests/scripts/generate_data_3.py
+++ b/test/test_rosbag/bag_migration_tests/scripts/generate_data_4.py
@@ -31,41 +31,40 @@
 # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 # POSSIBILITY OF SUCH DAMAGE.
 
-import rospy
 from test_rosbag.msg import *
 
 import rosbag
 
 def generate_data():
-    bag = rosbag.Bag("test/migrated_explicit_gen3.bag", "w")
-    m = MigratedExplicit(None, 17, 58.2, "aldfkja", 82)
+    bag = rosbag.Bag("test/migrated_explicit_gen4.bag", "w")
+    m = MigratedExplicit(None, 58.2, "aldfkja 17", 82)
     bag.write("migrated_explicit", m, genpy.Time())
     bag.close()
 
-    bag = rosbag.Bag("test/migrated_implicit_gen3.bag", "w")
-    m = MigratedImplicit(None, MigratedExplicit(None, 17, 58.2, "aldfkja", 82), "kljene", 16.32, 34)
+    bag = rosbag.Bag("test/migrated_implicit_gen4.bag", "w")
+    m = MigratedImplicit(None, MigratedExplicit(None, 58.2, "aldfkja 17", 82), "kljene", 16.32, 34)
     bag.write("migrated_implicit", m, genpy.Time())
     bag.close()
 
-    bag = rosbag.Bag("test/migrated_mixed_gen3.bag", "w")
-    m = MigratedMixed(None, MigratedImplicit(None, MigratedExplicit(None, 17, 58.2, "aldfkja", 82), "kljene", 16.32, 34), 59)
+    bag = rosbag.Bag("test/migrated_mixed_gen4.bag", "w")
+    m = MigratedMixed(None, MigratedImplicit(None, MigratedExplicit(None, 58.2, "aldfkja 17", 82), "kljene", 16.32, 34), 59)
     bag.write("migrated_mixed", m, genpy.Time())
     bag.close()
 
-    bag = rosbag.Bag("test/partially_migrated_gen3.bag", "w")
-    m = PartiallyMigrated(40, MigratedExplicit(None, 17, 58.2, "aldfkja", 82), "radasdk")
+    bag = rosbag.Bag("test/partially_migrated_gen4.bag", "w")
+    m = PartiallyMigrated(40, MigratedExplicit(None, 58.2, "aldfkja 17", 82), "radasdk", 63.4)
     bag.write("partially_migrated", m, genpy.Time())
     bag.close()
 
-    bag = rosbag.Bag("test/renamed_gen3.bag", "w")
-    m = Renamed3(2.17, [8, 2, 5, 1])
+    bag = rosbag.Bag("test/renamed_gen4.bag", "w")
+    m = Renamed4(2.17, [8, 2, 5, 1])
     bag.write("renamed", m, genpy.Time())
     bag.close()
 
-    bag = rosbag.Bag("test/converged_gen3.bag", "w")
+    bag = rosbag.Bag("test/converged_gen4.bag", "w")
     m = Converged([1.2, 3.4, 5.6, 7.8], [SimpleMigrated(11), SimpleMigrated(22), SimpleMigrated(33), SimpleMigrated(44)])
     bag.write("converged", m, genpy.Time())
     bag.close()
-        
+
 if __name__ == '__main__':
     generate_data()
diff --git a/test/test_rosbag/bag_migration_tests/scripts/generate_rules b/test/test_rosbag/bag_migration_tests/scripts/generate_rules
new file mode 100755
index 0000000..23d2bca
--- /dev/null
+++ b/test/test_rosbag/bag_migration_tests/scripts/generate_rules
@@ -0,0 +1,154 @@
+#!/bin/bash
+
+# Function that builds a message generation:
+# Note that we need to clean before in order to remove renamed messages.
+build_generation()
+{
+    # This hack is needed because `catkin_make_isolated` does NOT provide any option to clean the package;
+    # either way, even with `catkin_make clean`, it does NOT remove the package directory if .pyc files are inside it:
+    for dir in $(tr ':' '\n' <<< "$PYTHONPATH")
+    do
+        cd "$dir"
+        rm -rf test_rosbag
+        cd "$OLDPWD"
+    done
+
+    catkin_make_isolated -q --pkg test_rosbag --cmake-args -DMSG_DIRECTORY="msg_$1" >/dev/null
+}
+
+# Function that saves the full text definition of a message:
+save_msg()
+{
+    msg_type=${1/msg_*\//}
+    msg_type=test_rosbag/${msg_type/.msg}
+
+    saved_msg=${1/.msg/.saved}
+
+    if [ ! -f "$saved_msg" ]
+    then
+        rosrun rosbag savemsg.py "$msg_type" > "$saved_msg"
+
+        if [ $? -eq 0 ]
+        then
+            echo "Saved message $msg_type: $saved_msg"
+        else
+            echo "Failed to save message $msg_type!"
+        fi
+    else
+        echo "Message $msg_type already saved in $saved_msg"
+    fi
+}
+
+# Function that saves a message generation full definition (needed to create migration rules):
+save_generation()
+{
+    msgs=$(find "msg_$1" -name "*.msg")
+
+    for msg in $msgs
+    do
+        save_msg "$msg"
+    done
+}
+
+# Function that creates migration rules from a previous message generation to the current one:
+make_rules()
+{
+    saved_msgs=$(find "msg_$1" -name "*.saved")
+
+    for saved_msg in $saved_msgs
+    do
+        rules=$(find msg_* test -name "*.bmr" -print0 | xargs -0)
+        rule_file=${saved_msg/.saved/.bmr}
+
+        if [ ! -f "$rule_file" ]
+        then
+            # Note that we can't redirect the output to >/dev/null because for renamed/moved messages we need to
+            # provide the new message name.
+            rosrun rosbag makerule.py "$saved_msg" "$rule_file" $rules
+
+            if [ -f "$rule_file" ]
+            then
+                echo "Created rule for $saved_msg: $rule_file"
+                echo "Set valid = True, the order and implement the update method, or remove it if you don't want it."
+                echo "Then press ENTER."
+                read
+            else
+                echo "No rule needed for $saved_msg!"
+            fi
+        else
+            echo "Rule for $saved_msg already exists: $rule_file"
+        fi
+    done
+}
+
+# Take positional arguments that specifies the source and target message generations to create migration rules for:
+if [ $# -eq 2 ]
+then
+    GENERATION_SOURCE=$1
+    GENERATION_TARGET=$2
+else
+    echo "Usage  : $0 <source generation> <target generation>"
+    echo "Example: $0 gen4 current"
+    exit 1
+fi
+
+# Find the bag_migration_tests folder inside the test_rosbag package, since the .msg files are in the sub-folders
+# there:
+DESTINATION=$(rospack find test_rosbag)/bag_migration_tests
+
+# Build messages for the source generation:
+echo "Building generation: ${GENERATION_SOURCE}"
+build_generation "${GENERATION_SOURCE}"
+
+if [ $? -ne 0 ]
+then
+    >&2 echo "Failed to build messages for the source generation ${GENERATION_SOURCE}!"
+    exit 1
+fi
+
+echo
+
+# Save generation messages full text (needed to create migration rules):
+echo "Saving messages full text for generation: ${GENERATION_SOURCE}"
+cd "$DESTINATION"
+save_generation "${GENERATION_SOURCE}"
+cd "$OLDPWD"
+
+if [ $? -ne 0 ]
+then
+    >&2 echo "Failed to save messages full text for the source generation ${GENERATION_SOURCE}!"
+    exit 1
+fi
+
+echo
+
+# Build messages for the target generation:
+echo "Building generation: ${GENERATION_TARGET}"
+build_generation "${GENERATION_TARGET}"
+
+if [ $? -ne 0 ]
+then
+    >&2 echo "Failed to build messages for the target generation ${GENERATION_TARGET}!"
+    exit 1
+fi
+
+echo
+
+# Generate rules wrt to the source generation:
+echo "Making rules from source generation '${GENERATION_SOURCE}' to target generation '${GENERATION_TARGET}'"
+cd "$DESTINATION"
+make_rules "${GENERATION_SOURCE}"
+cd "$OLDPWD"
+
+if [ $? -ne 0 ]
+then
+    >&2 echo "Failed to generate rules!"
+    exit 1
+fi
+
+echo "* Remember that migration rules for renamed messages needs to be created manually!"
+echo "* Also remember that the migration rules in the files generated by this script might belong to other messages,"
+echo "  other than the one on the file name, so you should organize them properly!"
+
+# We don't really need to change the directory back to the old one, it's done automatically on exit:
+# cd $OLDPWD
diff --git a/test/test_rosbag/bag_migration_tests/test/migrate_test.py.in b/test/test_rosbag/bag_migration_tests/test/migrate_test.py.in
index 3577738..eab9b6c 100755
--- a/test/test_rosbag/bag_migration_tests/test/migrate_test.py.in
+++ b/test/test_rosbag/bag_migration_tests/test/migrate_test.py.in
@@ -58,7 +58,7 @@ class MigrationTest(unittest.TestCase):
     self.assertTrue(len(res[0][1]) == 1)
     self.assertTrue(not res[0][1][0].valid)
     self.assertEqual(res[0][1][0].old_class._md5sum, '4b12e5ff694b0e2a31b2ea9e0bd900f4')
-    self.assertEqual(res[0][1][0].new_class._md5sum, 'b5d640967dccef2a24697ec4b8a571ec')
+    self.assertEqual(res[0][1][0].new_class._md5sum, 'fed3471829c6040a8c84cd6c04ec5ab2')
 
 
   def test_subunmigrated(self):
@@ -73,7 +73,7 @@ class MigrationTest(unittest.TestCase):
     self.assertTrue(len(res[0][1]) == 1)
     self.assertTrue(not res[0][1][0].valid)
     self.assertEqual(res[0][1][0].old_class._md5sum, '4b12e5ff694b0e2a31b2ea9e0bd900f4')
-    self.assertEqual(res[0][1][0].new_class._md5sum, 'b5d640967dccef2a24697ec4b8a571ec')
+    self.assertEqual(res[0][1][0].new_class._md5sum, 'fed3471829c6040a8c84cd6c04ec5ab2')
 
   def do_partially_migrated(self, N):
     tmp_rule_files = ['migrated_explicit_rules.bmr', 'migrated_mixed_rules.bmr', 'migrated_addsub_rules.bmr', 'partially_migrated_rules.bmr']
@@ -86,9 +86,9 @@ class MigrationTest(unittest.TestCase):
 
     self.assertTrue(len(res[0][1]) == 1)
     self.assertTrue(not res[0][1][0].valid)
-    self.assertEqual(res[0][1][0].old_class._md5sum, 'aba12af164ecf3f5cd150fb990205c4b')
-    self.assertEqual(res[0][1][0].new_class._md5sum, 'b942bf4a41fb2bebc502889fd8981dfe')
-    
+    self.assertEqual(res[0][1][0].old_class._md5sum, '9fafd0ad3f442b8a7908d03e9bb64de2')
+    self.assertEqual(res[0][1][0].new_class._md5sum, '45f99fcf57ef956dd2a6a16472643507')
+
 
   def test_partially_migrated_gen1(self):
     self.do_partially_migrated(1)
@@ -99,6 +99,9 @@ class MigrationTest(unittest.TestCase):
   def test_partially_migrated_gen3(self):
     self.do_partially_migrated(3)
 
+  def test_partially_migrated_gen4(self):
+    self.do_partially_migrated(4)
+
 
   def test_addsub(self):
     tmp_rule_files = ['migrated_explicit_rules.bmr', 'migrated_mixed_rules.bmr', 'migrated_addsub_rules.bmr']
@@ -140,9 +143,9 @@ class MigrationTest(unittest.TestCase):
 
     self.assertTrue(len(msgs) > 0)
 
-    self.assertEqual(msgs[0][1].afield2, struct.unpack('<f',struct.pack('<f',58.2))[0])
+    self.assertEqual(msgs[0][1].field2, struct.unpack('<f',struct.pack('<f',58.2))[0])
     self.assertEqual(msgs[0][1].combo_field3, "aldfkja 17")
-    self.assertEqual(msgs[0][1].afield4, 82)
+    self.assertEqual(msgs[0][1].field4, 82)
 
   def test_migrated_explicit_gen1(self):
     self.do_migrated_explicit(1)
@@ -153,6 +156,9 @@ class MigrationTest(unittest.TestCase):
   def test_migrated_explicit_gen3(self):
     self.do_migrated_explicit(3)
 
+  def test_migrated_explicit_gen4(self):
+    self.do_migrated_explicit(4)
+
 
 
   def do_migrated_implicit(self, N):
@@ -173,9 +179,9 @@ class MigrationTest(unittest.TestCase):
 
     self.assertTrue(len(msgs) > 0)
 
-    self.assertEqual(msgs[0][1].field4.afield2, struct.unpack('<f',struct.pack('<f',58.2))[0])
+    self.assertEqual(msgs[0][1].field4.field2, struct.unpack('<f',struct.pack('<f',58.2))[0])
     self.assertEqual(msgs[0][1].field4.combo_field3, "aldfkja 17")
-    self.assertEqual(msgs[0][1].field4.afield4, 82)
+    self.assertEqual(msgs[0][1].field4.field4, 82)
 
     self.assertEqual(msgs[0][1].field1, 34)
     self.assertEqual(msgs[0][1].field2, struct.unpack('<f',struct.pack('<f',16.32))[0])
@@ -191,6 +197,9 @@ class MigrationTest(unittest.TestCase):
   def test_migrated_implicit_gen3(self):
     self.do_migrated_implicit(3)
 
+  def test_migrated_implicit_gen4(self):
+    self.do_migrated_implicit(4)
+
 
 
   def do_migrated_mixed(self, N):
@@ -211,9 +220,9 @@ class MigrationTest(unittest.TestCase):
 
     self.assertTrue(len(msgs) > 0)
 
-    self.assertEqual(msgs[0][1].field1.field4.afield2, struct.unpack('<f',struct.pack('<f',58.2))[0])
+    self.assertEqual(msgs[0][1].field1.field4.field2, struct.unpack('<f',struct.pack('<f',58.2))[0])
     self.assertEqual(msgs[0][1].field1.field4.combo_field3, "aldfkja 17")
-    self.assertEqual(msgs[0][1].field1.field4.afield4, 82)
+    self.assertEqual(msgs[0][1].field1.field4.field4, 82)
 
     self.assertEqual(msgs[0][1].field1.field1, 34)
     self.assertEqual(msgs[0][1].field1.field2, struct.unpack('<f',struct.pack('<f',16.32))[0])
@@ -230,6 +239,9 @@ class MigrationTest(unittest.TestCase):
   def test_migrated_mixed_gen3(self):
     self.do_migrated_mixed(3)
 
+  def test_migrated_mixed_gen4(self):
+    self.do_migrated_mixed(4)
+
 
 
   def do_renamed(self, N):
@@ -251,7 +263,7 @@ class MigrationTest(unittest.TestCase):
     self.assertTrue(len(msgs) > 0)
 
 
-    self.assertEqual(msgs[0][1]._type, 'test_rosbag/Renamed4', 'Type name is wrong')
+    self.assertEqual(msgs[0][1]._type, 'test_rosbag/Renamed5', 'Type name is wrong')
     self.assertEqual(msgs[0][1].foo, struct.unpack('<d',struct.pack('<d',2.17))[0])
     self.assertEqual(msgs[0][1].bar, (8, 2, 5, 1))
 
@@ -265,6 +277,9 @@ class MigrationTest(unittest.TestCase):
   def test_renamed_gen3(self):
     self.do_renamed(3)
 
+  def test_renamed_gen4(self):
+    self.do_renamed(4)
+
 
   def do_converged(self, N):
     tmp_rule_files = ['migrated_explicit_rules.bmr', 'migrated_mixed_rules.bmr', 'migrated_addsub_rules.bmr', 'renamed_rules.bmr', 'simple_migrated_rules.bmr', 'converged_rules.bmr']
@@ -305,6 +320,9 @@ class MigrationTest(unittest.TestCase):
   def test_converged_gen3(self):
     self.do_converged(3)
 
+  def test_converged_gen4(self):
+    self.do_converged(4)
+
 
   def do_convergent(self, N):
     tmp_rule_files = ['migrated_explicit_rules.bmr', 'migrated_mixed_rules.bmr', 'migrated_addsub_rules.bmr', 'renamed_rules.bmr', 'simple_migrated_rules.bmr', 'converged_rules.bmr']
diff --git a/test/test_rosbag/bag_migration_tests/test/migrated_explicit_rules.bmr b/test/test_rosbag/bag_migration_tests/test/migrated_explicit_rules.bmr
index b8d633f..17f5d8f 100644
--- a/test/test_rosbag/bag_migration_tests/test/migrated_explicit_rules.bmr
+++ b/test/test_rosbag/bag_migration_tests/test/migrated_explicit_rules.bmr
@@ -1,19 +1,22 @@
 class update_test_rosbag_MigratedExplicit_c7936d50a749a1f589d6fc81eae24b34(MessageUpdateRule):
     old_type = "test_rosbag/MigratedExplicit"
-    new_type = "test_rosbag/MigratedExplicit"
     old_full_text = """
 Header  header
 int32   field1 #17
 float32 field2 #58.2
 string  field3 #"aldfkja"
+
 ================================================================================
-MSG: roslib/Header
-#Standard metadata for higher-level flow data types
-#sequence ID: consecutively increasing ID
+MSG: std_msgs/Header
+# Standard metadata for higher-level stamped data types.
+# This is generally used to communicate timestamped data 
+# in a particular coordinate frame.
+# 
+# sequence ID: consecutively increasing ID 
 uint32 seq
 #Two-integer timestamp that is expressed as:
-# * stamp.secs: seconds (stamp_secs) since epoch
-# * stamp.nsecs: nanoseconds since stamp_secs
+# * stamp.sec: seconds (stamp_secs) since epoch (in Python the variable is called 'secs')
+# * stamp.nsec: nanoseconds since stamp_secs (in Python the variable is called 'nsecs')
 # time-handling sugar is provided by the client library
 time stamp
 #Frame this data is associated with
@@ -21,20 +24,26 @@ time stamp
 # 1: global frame
 string frame_id
 """
+
+    new_type = "test_rosbag/MigratedExplicit"
     new_full_text = """
 Header  header
 int32   field1 #17
 float32 field2 #58.2
 string  field3 #"aldfkja"
 int32   field4 #82
+
 ================================================================================
-MSG: roslib/Header
-#Standard metadata for higher-level flow data types
-#sequence ID: consecutively increasing ID
+MSG: std_msgs/Header
+# Standard metadata for higher-level stamped data types.
+# This is generally used to communicate timestamped data 
+# in a particular coordinate frame.
+# 
+# sequence ID: consecutively increasing ID 
 uint32 seq
 #Two-integer timestamp that is expressed as:
-# * stamp.secs: seconds (stamp_secs) since epoch
-# * stamp.nsecs: nanoseconds since stamp_secs
+# * stamp.sec: seconds (stamp_secs) since epoch (in Python the variable is called 'secs')
+# * stamp.nsec: nanoseconds since stamp_secs (in Python the variable is called 'nsecs')
 # time-handling sugar is provided by the client library
 time stamp
 #Frame this data is associated with
@@ -44,10 +53,8 @@ string frame_id
 """
 
     order = 0
-
     migrated_types = [
-        ("Header","Header"),
-    ]
+        ("Header","Header"),]
 
     valid = True
 
@@ -58,25 +65,26 @@ string frame_id
         new_msg.field3 = old_msg.field3
         new_msg.field4 = 82
 
-
-
 class update_test_rosbag_MigratedExplicit_fa072fb3cfcf105e1e5609a7467e2a14(MessageUpdateRule):
     old_type = "test_rosbag/MigratedExplicit"
-    new_type = "test_rosbag/MigratedExplicit"
     old_full_text = """
 Header  header
 int32   field1 #17
 float32 field2 #58.2
 string  field3 #"aldfkja"
 int32   field4 #82
+
 ================================================================================
-MSG: roslib/Header
-#Standard metadata for higher-level flow data types
-#sequence ID: consecutively increasing ID
+MSG: std_msgs/Header
+# Standard metadata for higher-level stamped data types.
+# This is generally used to communicate timestamped data
+# in a particular coordinate frame.
+#
+# sequence ID: consecutively increasing ID
 uint32 seq
 #Two-integer timestamp that is expressed as:
-# * stamp.secs: seconds (stamp_secs) since epoch
-# * stamp.nsecs: nanoseconds since stamp_secs
+# * stamp.sec: seconds (stamp_secs) since epoch (in Python the variable is called 'secs')
+# * stamp.nsec: nanoseconds since stamp_secs (in Python the variable is called 'nsecs')
 # time-handling sugar is provided by the client library
 time stamp
 #Frame this data is associated with
@@ -84,20 +92,26 @@ time stamp
 # 1: global frame
 string frame_id
 """
+
+    new_type = "test_rosbag/MigratedExplicit"
     new_full_text = """
 Header  header
 int32   afield1 #17
 float32 afield2 #58.2
 string  afield3 #"aldfkja"
 int32   afield4 #82
+
 ================================================================================
-MSG: roslib/Header
-#Standard metadata for higher-level flow data types
-#sequence ID: consecutively increasing ID
+MSG: std_msgs/Header
+# Standard metadata for higher-level stamped data types.
+# This is generally used to communicate timestamped data
+# in a particular coordinate frame.
+#
+# sequence ID: consecutively increasing ID
 uint32 seq
 #Two-integer timestamp that is expressed as:
-# * stamp.secs: seconds (stamp_secs) since epoch
-# * stamp.nsecs: nanoseconds since stamp_secs
+# * stamp.sec: seconds (stamp_secs) since epoch (in Python the variable is called 'secs')
+# * stamp.nsec: nanoseconds since stamp_secs (in Python the variable is called 'nsecs')
 # time-handling sugar is provided by the client library
 time stamp
 #Frame this data is associated with
@@ -105,11 +119,10 @@ time stamp
 # 1: global frame
 string frame_id
 """
-    order = 1
 
+    order = 1
     migrated_types = [
-        ("Header","Header"),
-    ]
+        ("Header","Header"),]
 
     valid = True
 
@@ -120,24 +133,26 @@ string frame_id
         new_msg.afield3 = old_msg.field3
         new_msg.afield4 = old_msg.field4
 
-
 class update_test_rosbag_MigratedExplicit_0a3e03fbb60b5f9abd4beedae6080fce(MessageUpdateRule):
     old_type = "test_rosbag/MigratedExplicit"
-    new_type = "test_rosbag/MigratedExplicit"
     old_full_text = """
 Header  header
 int32   afield1 #17
 float32 afield2 #58.2
 string  afield3 #"aldfkja"
 int32   afield4 #82
+
 ================================================================================
-MSG: roslib/Header
-#Standard metadata for higher-level flow data types
-#sequence ID: consecutively increasing ID
+MSG: std_msgs/Header
+# Standard metadata for higher-level stamped data types.
+# This is generally used to communicate timestamped data
+# in a particular coordinate frame.
+#
+# sequence ID: consecutively increasing ID
 uint32 seq
 #Two-integer timestamp that is expressed as:
-# * stamp.secs: seconds (stamp_secs) since epoch
-# * stamp.nsecs: nanoseconds since stamp_secs
+# * stamp.sec: seconds (stamp_secs) since epoch (in Python the variable is called 'secs')
+# * stamp.nsec: nanoseconds since stamp_secs (in Python the variable is called 'nsecs')
 # time-handling sugar is provided by the client library
 time stamp
 #Frame this data is associated with
@@ -145,19 +160,25 @@ time stamp
 # 1: global frame
 string frame_id
 """
+
+    new_type = "test_rosbag/MigratedExplicit"
     new_full_text = """
 Header  header
 float32 afield2 #58.2
 string  combo_field3 #"aldfkja 17"
 int32   afield4 #82
+
 ================================================================================
-MSG: roslib/Header
-#Standard metadata for higher-level flow data types
-#sequence ID: consecutively increasing ID
+MSG: std_msgs/Header
+# Standard metadata for higher-level stamped data types.
+# This is generally used to communicate timestamped data 
+# in a particular coordinate frame.
+# 
+# sequence ID: consecutively increasing ID 
 uint32 seq
 #Two-integer timestamp that is expressed as:
-# * stamp.secs: seconds (stamp_secs) since epoch
-# * stamp.nsecs: nanoseconds since stamp_secs
+# * stamp.sec: seconds (stamp_secs) since epoch (in Python the variable is called 'secs')
+# * stamp.nsec: nanoseconds since stamp_secs (in Python the variable is called 'nsecs')
 # time-handling sugar is provided by the client library
 time stamp
 #Frame this data is associated with
@@ -167,10 +188,8 @@ string frame_id
 """
 
     order = 2
-
     migrated_types = [
-        ("Header","Header"),
-    ]
+        ("Header","Header"),]
 
     valid = True
 
@@ -179,3 +198,68 @@ string frame_id
         new_msg.afield2 = old_msg.afield2
         new_msg.combo_field3 = old_msg.afield3 + ' ' + str(old_msg.afield1)
         new_msg.afield4 = old_msg.afield4
+
+class update_test_rosbag_MigratedExplicit_615f47263d68f3ea2dee962dc22dd171(MessageUpdateRule):
+    old_type = "test_rosbag/MigratedExplicit"
+    old_full_text = """
+Header  header
+float32 afield2 #58.2
+string  combo_field3 #"aldfkja 17"
+int32   afield4 #82
+
+================================================================================
+MSG: std_msgs/Header
+# Standard metadata for higher-level stamped data types.
+# This is generally used to communicate timestamped data 
+# in a particular coordinate frame.
+# 
+# sequence ID: consecutively increasing ID 
+uint32 seq
+#Two-integer timestamp that is expressed as:
+# * stamp.sec: seconds (stamp_secs) since epoch (in Python the variable is called 'secs')
+# * stamp.nsec: nanoseconds since stamp_secs (in Python the variable is called 'nsecs')
+# time-handling sugar is provided by the client library
+time stamp
+#Frame this data is associated with
+# 0: no frame
+# 1: global frame
+string frame_id
+"""
+
+    new_type = "test_rosbag/MigratedExplicit"
+    new_full_text = """
+Header  header
+float32 field2 #58.2
+string  combo_field3 #"aldfkja 17"
+int32   field4 #82
+
+================================================================================
+MSG: std_msgs/Header
+# Standard metadata for higher-level stamped data types.
+# This is generally used to communicate timestamped data 
+# in a particular coordinate frame.
+# 
+# sequence ID: consecutively increasing ID 
+uint32 seq
+#Two-integer timestamp that is expressed as:
+# * stamp.sec: seconds (stamp_secs) since epoch (in Python the variable is called 'secs')
+# * stamp.nsec: nanoseconds since stamp_secs (in Python the variable is called 'nsecs')
+# time-handling sugar is provided by the client library
+time stamp
+#Frame this data is associated with
+# 0: no frame
+# 1: global frame
+string frame_id
+"""
+
+    order = 3
+    migrated_types = [
+        ("Header","Header"),]
+
+    valid = True
+
+    def update(self, old_msg, new_msg):
+        self.migrate(old_msg.header, new_msg.header)
+        new_msg.field2 = old_msg.afield2
+        new_msg.combo_field3 = old_msg.combo_field3
+        new_msg.field4 = old_msg.afield4
diff --git a/test/test_rosbag/bag_migration_tests/test/migrated_mixed_rules.bmr b/test/test_rosbag/bag_migration_tests/test/migrated_mixed_rules.bmr
index 8146ebe..efb02c0 100644
--- a/test/test_rosbag/bag_migration_tests/test/migrated_mixed_rules.bmr
+++ b/test/test_rosbag/bag_migration_tests/test/migrated_mixed_rules.bmr
@@ -4,14 +4,18 @@ class update_test_rosbag_MigratedMixed_5568494133a082ad58ef1aa391f47e2b(MessageU
 Header             header
 MigratedImplicit   field1 #(34, 16.32, "kjljene", (17, 58.2, "aldfkja", 82))
 
+
 ================================================================================
-MSG: roslib/Header
-#Standard metadata for higher-level flow data types
-#sequence ID: consecutively increasing ID
+MSG: std_msgs/Header
+# Standard metadata for higher-level stamped data types.
+# This is generally used to communicate timestamped data 
+# in a particular coordinate frame.
+# 
+# sequence ID: consecutively increasing ID 
 uint32 seq
 #Two-integer timestamp that is expressed as:
-# * stamp.secs: seconds (stamp_secs) since epoch
-# * stamp.nsecs: nanoseconds since stamp_secs
+# * stamp.sec: seconds (stamp_secs) since epoch (in Python the variable is called 'secs')
+# * stamp.nsec: nanoseconds since stamp_secs (in Python the variable is called 'nsecs')
 # time-handling sugar is provided by the client library
 time stamp
 #Frame this data is associated with
@@ -43,13 +47,16 @@ MigratedImplicit   field1 #((17, 58.2, "aldfkja", 82), "kjljene", 16.32, 34)
 int32              field2 #59
 
 ================================================================================
-MSG: roslib/Header
-#Standard metadata for higher-level flow data types
-#sequence ID: consecutively increasing ID
+MSG: std_msgs/Header
+# Standard metadata for higher-level stamped data types.
+# This is generally used to communicate timestamped data 
+# in a particular coordinate frame.
+# 
+# sequence ID: consecutively increasing ID 
 uint32 seq
 #Two-integer timestamp that is expressed as:
-# * stamp.secs: seconds (stamp_secs) since epoch
-# * stamp.nsecs: nanoseconds since stamp_secs
+# * stamp.sec: seconds (stamp_secs) since epoch (in Python the variable is called 'secs')
+# * stamp.nsec: nanoseconds since stamp_secs (in Python the variable is called 'nsecs')
 # time-handling sugar is provided by the client library
 time stamp
 #Frame this data is associated with
@@ -65,6 +72,8 @@ string  field3 #"kljene"
 float32 field2 #16.32
 int32   field1 #34
 
+
+
 ================================================================================
 MSG: test_rosbag/MigratedExplicit
 Header  header
@@ -77,9 +86,7 @@ int32   afield4 #82
     order = 0
     migrated_types = [
         ("Header","Header"),
-        ("MigratedImplicit","MigratedImplicit"),
-
-    ]
+        ("MigratedImplicit","MigratedImplicit"),]
 
     valid = True
 
diff --git a/test/test_rosbag/bag_migration_tests/test/partially_migrated_rules.bmr b/test/test_rosbag/bag_migration_tests/test/partially_migrated_rules.bmr
index b82901a..9e6c4fb 100644
--- a/test/test_rosbag/bag_migration_tests/test/partially_migrated_rules.bmr
+++ b/test/test_rosbag/bag_migration_tests/test/partially_migrated_rules.bmr
@@ -65,3 +65,76 @@ string frame_id
         new_msg.field1 = old_msg.field1
         self.migrate(old_msg.field2, new_msg.field2)
         new_msg.field3 = 'radasdk'
+
+class update_test_rosbag_PartiallyMigrated_aba12af164ecf3f5cd150fb990205c4b(MessageUpdateRule):
+    old_type = "test_rosbag/PartiallyMigrated"
+    old_full_text = """
+int32            field1 # 40
+MigratedExplicit field2 # (17, 58.2, "aldfkja", 82)
+string           field3 # "radasdk"
+
+================================================================================
+MSG: test_rosbag/MigratedExplicit
+Header  header
+int32   afield1 #17
+float32 afield2 #58.2
+string  afield3 #"aldfkja"
+int32   afield4 #82
+================================================================================
+MSG: std_msgs/Header
+#Standard metadata for higher-level flow data types
+#sequence ID: consecutively increasing ID
+uint32 seq
+#Two-integer timestamp that is expressed as:
+# * stamp.secs: seconds (stamp_secs) since epoch
+# * stamp.nsecs: nanoseconds since stamp_secs
+# time-handling sugar is provided by the client library
+time stamp
+#Frame this data is associated with
+# 0: no frame
+# 1: global frame
+string frame_id
+"""
+
+    new_type = "test_rosbag/PartiallyMigrated"
+    new_full_text = """
+int32            field1 # 40
+MigratedExplicit field2 # (58.2, "aldfkja 17", 82)
+string           field3 # "radasdk"
+float32          field4 # 63.4
+
+================================================================================
+MSG: test_rosbag/MigratedExplicit
+Header  header
+float32 afield2 #58.2
+string  combo_field3 #"aldfkja 17"
+int32   afield4 #82
+================================================================================
+MSG: std_msgs/Header
+# Standard metadata for higher-level stamped data types.
+# This is generally used to communicate timestamped data 
+# in a particular coordinate frame.
+# 
+# sequence ID: consecutively increasing ID 
+uint32 seq
+#Two-integer timestamp that is expressed as:
+# * stamp.sec: seconds (stamp_secs) since epoch (in Python the variable is called 'secs')
+# * stamp.nsec: nanoseconds since stamp_secs (in Python the variable is called 'nsecs')
+# time-handling sugar is provided by the client library
+time stamp
+#Frame this data is associated with
+# 0: no frame
+# 1: global frame
+string frame_id
+"""
+
+    order = 1
+    migrated_types = [("MigratedExplicit","MigratedExplicit"),]
+
+    valid = True
+
+    def update(self, old_msg, new_msg):
+        new_msg.field1 = old_msg.field1
+        self.migrate(old_msg.field2, new_msg.field2)
+        new_msg.field3 = old_msg.field3
+        new_msg.field4 = 63.4
diff --git a/test/test_rosbag/bag_migration_tests/test/renamed_rules.bmr b/test/test_rosbag/bag_migration_tests/test/renamed_rules.bmr
index 4267ddf..8473fb5 100644
--- a/test/test_rosbag/bag_migration_tests/test/renamed_rules.bmr
+++ b/test/test_rosbag/bag_migration_tests/test/renamed_rules.bmr
@@ -63,3 +63,25 @@ int32[4] bar  # [8, 2, 5, 1]
     def update(self, old_msg, new_msg):
         new_msg.foo = old_msg.foo
         new_msg.bar = old_msg.bar
+
+class update_test_rosbag_Renamed4_dd19d6452bb5e45bb900f81fed30ae83(MessageUpdateRule):
+    old_type = "test_rosbag/Renamed4"
+    old_full_text = """
+float64  foo  # 2.17
+int32[4] bar  # [8, 2, 5, 1]
+"""
+
+    new_type = "test_rosbag/Renamed5"
+    new_full_text = """
+float64  foo  # 2.17
+int32[4] bar  # [8, 2, 5, 1]
+"""
+
+    order = 0
+    migrated_types = []
+
+    valid = True
+
+    def update(self, old_msg, new_msg):
+        new_msg.foo = old_msg.foo
+        new_msg.bar = old_msg.bar
diff --git a/test/test_rosbag/bag_migration_tests/test/simple_migrated_rules.bmr b/test/test_rosbag/bag_migration_tests/test/simple_migrated_rules.bmr
index 63e18dc..7d1a727 100644
--- a/test/test_rosbag/bag_migration_tests/test/simple_migrated_rules.bmr
+++ b/test/test_rosbag/bag_migration_tests/test/simple_migrated_rules.bmr
@@ -10,9 +10,7 @@ int32 data2 # 42
 """
 
     order = 0
-    migrated_types = [
-
-    ]
+    migrated_types = []
 
     valid = True
 
@@ -46,7 +44,7 @@ int32 data3 # 42
 
     new_type = "test_rosbag/SimpleMigrated"
     new_full_text = """
-int32 data # 42
+int32 data4 # 42
 """
 
     order = 2
@@ -55,4 +53,23 @@ int32 data # 42
     valid = True
 
     def update(self, old_msg, new_msg):
-        new_msg.data = old_msg.data3
+        new_msg.data4 = old_msg.data3
+
+class update_test_rosbag_SimpleMigrated_3a614a5e4e7251529dc16a74525c515a(MessageUpdateRule):
+    old_type = "test_rosbag/SimpleMigrated"
+    old_full_text = """
+int32 data4 # 42
+"""
+
+    new_type = "test_rosbag/SimpleMigrated"
+    new_full_text = """
+int32 data # 42
+"""
+
+    order = 3
+    migrated_types = []
+
+    valid = True
+
+    def update(self, old_msg, new_msg):
+        new_msg.data = old_msg.data4
diff --git a/test/test_rosbag/package.xml b/test/test_rosbag/package.xml
index ab8234c..e35890d 100644
--- a/test/test_rosbag/package.xml
+++ b/test/test_rosbag/package.xml
@@ -1,6 +1,6 @@
 <package>
   <name>test_rosbag</name>
-  <version>1.12.6</version>
+  <version>1.13.1</version>
   <description>
     A package containing the unit tests for rosbag.
   </description>
diff --git a/test/test_rosbag/test/test_bag.py b/test/test_rosbag/test/test_bag.py
index 86deb5c..4cf249c 100755
--- a/test/test_rosbag/test/test_bag.py
+++ b/test/test_rosbag/test/test_bag.py
@@ -287,7 +287,7 @@ class TestRosbag(unittest.TestCase):
     def test_get_message_count(self):
         fn = '/tmp/test_get_message_count.bag'
         with rosbag.Bag(fn, mode='w') as bag:
-            for i in xrange(100):
+            for i in range(100):
                 bag.write("/test_bag", Int32(data=i))
                 bag.write("/test_bag", String(data='also'))
                 bag.write("/test_bag/more", String(data='alone'))
@@ -303,7 +303,7 @@ class TestRosbag(unittest.TestCase):
         
         # No Compression
         with rosbag.Bag(fn, mode='w') as bag:
-            for i in xrange(100):
+            for i in range(100):
                 bag.write("/test_bag", Int32(data=i))
                 
         with rosbag.Bag(fn) as bag:
@@ -314,7 +314,7 @@ class TestRosbag(unittest.TestCase):
             self.assertEquals(info.compressed, 5166)
         
         with rosbag.Bag(fn, mode='w', compression=rosbag.Compression.BZ2) as bag:
-            for i in xrange(100):
+            for i in range(100):
                 bag.write("/test_bag", Int32(data=i))
                 
         with rosbag.Bag(fn) as bag:
@@ -331,7 +331,7 @@ class TestRosbag(unittest.TestCase):
         fn = '/tmp/test_get_time.bag'
         
         with rosbag.Bag(fn, mode='w') as bag:
-            for i in xrange(100):
+            for i in range(100):
                 bag.write("/test_bag", Int32(data=i), t=genpy.Time.from_sec(i))
                 
         with rosbag.Bag(fn) as bag:
@@ -358,7 +358,7 @@ class TestRosbag(unittest.TestCase):
         topic_1 = "/test_bag"
         topic_2 = "/test_bag/more"
         with rosbag.Bag(fn, mode='w') as bag:
-            for i in xrange(100):
+            for i in range(100):
                 bag.write(topic_1, Int32(data=i))
                 bag.write(topic_1, String(data='also'))
                 bag.write(topic_2, String(data='alone'))
diff --git a/test/test_rosbag_storage/CMakeLists.txt b/test/test_rosbag_storage/CMakeLists.txt
index 0ced5bf..fa2438d 100644
--- a/test/test_rosbag_storage/CMakeLists.txt
+++ b/test/test_rosbag_storage/CMakeLists.txt
@@ -15,4 +15,8 @@ if(CATKIN_ENABLE_TESTING)
   if(TARGET create_and_iterate_bag)
     target_link_libraries(create_and_iterate_bag ${catkin_LIBRARIES})
   endif()
+  catkin_add_gtest(swap_bags src/swap_bags.cpp)
+  if(TARGET swap_bags)
+    target_link_libraries(swap_bags ${catkin_LIBRARIES})
+  endif()
 endif()
diff --git a/test/test_rosbag_storage/package.xml b/test/test_rosbag_storage/package.xml
index 7d79e04..2c5646e 100644
--- a/test/test_rosbag_storage/package.xml
+++ b/test/test_rosbag_storage/package.xml
@@ -1,6 +1,6 @@
 <package>
   <name>test_rosbag_storage</name>
-  <version>1.12.6</version>
+  <version>1.13.1</version>
   <description>
     A package containing the unit tests for rosbag_storage.
   </description>
diff --git a/test/test_rosbag_storage/src/create_and_iterate_bag.cpp b/test/test_rosbag_storage/src/create_and_iterate_bag.cpp
index 37d0852..23c91dc 100644
--- a/test/test_rosbag_storage/src/create_and_iterate_bag.cpp
+++ b/test/test_rosbag_storage/src/create_and_iterate_bag.cpp
@@ -10,71 +10,104 @@
 #include "boost/foreach.hpp"
 #include <gtest/gtest.h>
 
+void create_test_bag(const std::string &filename)
+{
+  rosbag::Bag bag;
+  bag.open(filename, rosbag::bagmode::Write);
+
+  std_msgs::String str;
+  str.data = std::string("foo");
+
+  std_msgs::Int32 i;
+  i.data = 42;
+
+  bag.write("chatter", ros::Time::now(), str);
+  bag.write("numbers", ros::Time::now(), i);
+
+  bag.close();
+}
 
-TEST(rosbag_storage, create_and_iterate_bag)
+const char* bag_filename = "/tmp/rosbag_storage_create_and_iterate_bag.bag";
+
+TEST(rosbag_storage, iterator_copy_constructor)
 {
-  const char* bag_filename = "/tmp/rosbag_storage_create_and_iterate_bag.bag";
-  {
-    rosbag::Bag bag;
-    bag.open(bag_filename, rosbag::bagmode::Write);
-
-    std_msgs::String str;
-    str.data = std::string("foo");
-  
-    std_msgs::Int32 i;
-    i.data = 42;
-  
-    bag.write("chatter", ros::Time::now(), str);
-    bag.write("numbers", ros::Time::now(), i);
-
-    bag.close();
-  }
+  // copy ctor
+  rosbag::Bag bag;
+  bag.open(bag_filename, rosbag::bagmode::Read);
+  rosbag::View view(bag, rosbag::TopicQuery("numbers"));
+  rosbag::View::const_iterator it0 = view.begin();
+  EXPECT_EQ(42, it0->instantiate<std_msgs::Int32>()->data);
+  rosbag::View::const_iterator it1(it0);
+  EXPECT_EQ(it0, it1);
+  EXPECT_EQ(42, it1->instantiate<std_msgs::Int32>()->data);
+  ++it1;
+  EXPECT_NE(it0, it1);
+  EXPECT_EQ(42, it0->instantiate<std_msgs::Int32>()->data);
+}
 
-  {
-    rosbag::Bag bag;
-    bag.open(bag_filename, rosbag::bagmode::Read);
+TEST(rosbag_storage, iterator_copy_assignment)
+{
+  // copy assignment
+  rosbag::Bag bag;
+  bag.open(bag_filename, rosbag::bagmode::Read);
+  rosbag::View view(bag, rosbag::TopicQuery("numbers"));
+  rosbag::View::const_iterator it0 = view.begin();
+  EXPECT_EQ(42, it0->instantiate<std_msgs::Int32>()->data);
+  rosbag::View::const_iterator it1;
+  it1 = it0;
+  EXPECT_EQ(it0, it1);
+  EXPECT_EQ(42, it1->instantiate<std_msgs::Int32>()->data);
+  ++it1;
+  EXPECT_NE(it0, it1);
+  EXPECT_EQ(42, it0->instantiate<std_msgs::Int32>()->data);
+}
+
+TEST(rosbag_storage, iterate_bag)
+{
+  rosbag::Bag bag;
+  bag.open(bag_filename, rosbag::bagmode::Read);
 
-    std::vector<std::string> topics;
-    topics.push_back(std::string("chatter"));
-    topics.push_back(std::string("numbers"));
+  std::vector<std::string> topics;
+  topics.push_back(std::string("chatter"));
+  topics.push_back(std::string("numbers"));
 
-    rosbag::View view(bag, rosbag::TopicQuery(topics));
+  rosbag::View view(bag, rosbag::TopicQuery(topics));
 
-    BOOST_FOREACH(rosbag::MessageInstance const m, view)
+  BOOST_FOREACH(rosbag::MessageInstance const m, view)
+  {
+    std_msgs::String::ConstPtr s = m.instantiate<std_msgs::String>();
+    if (s != NULL)
     {
-      std_msgs::String::ConstPtr s = m.instantiate<std_msgs::String>();
-      if (s != NULL)
+      if(s->data == std::string("foo")) {
+        printf("Successfully checked string foo\n");
+      }
+      else
       {
-        if(s->data == std::string("foo")) { 
-          printf("Successfully checked string foo\n");
-        }
-        else
-        {
-          printf("Failed checked string foo\n");
-          FAIL();
-        }
+        printf("Failed checked string foo\n");
+        FAIL();
       }
+    }
 
-      std_msgs::Int32::ConstPtr i = m.instantiate<std_msgs::Int32>();
-      if (i != NULL)
+    std_msgs::Int32::ConstPtr i = m.instantiate<std_msgs::Int32>();
+    if (i != NULL)
+    {
+      if (i->data == 42) {
+        printf("Successfully checked value 42\n");
+      }
+      else
       {
-        if (i->data == 42) { 
-          printf("Successfully checked value 42\n");
-        }
-        else
-        {
-          printf("Failed checked value 42.\n"); 
-          FAIL();
-        }
+        printf("Failed checked value 42.\n");
+        FAIL();
       }
     }
-
-    bag.close();
   }
+
+  bag.close();
 }
 
 int main(int argc, char **argv) {
     ros::Time::init();
+    create_test_bag(bag_filename);
 
     testing::InitGoogleTest(&argc, argv);
     return RUN_ALL_TESTS();
diff --git a/test/test_rosbag_storage/src/swap_bags.cpp b/test/test_rosbag_storage/src/swap_bags.cpp
new file mode 100644
index 0000000..3940f18
--- /dev/null
+++ b/test/test_rosbag_storage/src/swap_bags.cpp
@@ -0,0 +1,101 @@
+#include "ros/time.h"
+#include "rosbag/bag.h"
+#include "rosbag/view.h"
+#include "std_msgs/Int32.h"
+
+#include "boost/foreach.hpp"
+#include <gtest/gtest.h>
+
+void writeBags(rosbag::CompressionType a, rosbag::CompressionType b) {
+    using std::swap;
+    rosbag::Bag bag1("/tmp/swap1.bag", rosbag::bagmode::Write);
+    rosbag::Bag bag2("/tmp/swap2.bag", rosbag::bagmode::Write);
+
+    // In the end "/tmp/swap1.bag" should have CompressionType a and contain two messages of value a.
+    // "/tmp/swap2.bag" should have CompressionType b and contain two messages of value b.
+    // We use these pointers to track the bags accordingly.
+
+    rosbag::Bag* a_bag = &bag1;
+    rosbag::Bag* b_bag = &bag2;
+
+    std_msgs::Int32 a_msg, b_msg;
+    a_msg.data = a;
+    b_msg.data = b;
+
+    swap(bag1, bag2);
+    swap(a_bag, b_bag);
+
+    a_bag->setCompression(a);
+    b_bag->setCompression(b);
+
+    swap(bag1, bag2);
+    swap(a_bag, b_bag);
+
+    a_bag->write("/data", ros::Time::now(), a_msg);
+    b_bag->write("/data", ros::Time::now(), b_msg);
+
+    swap(bag1, bag2);
+    swap(a_bag, b_bag);
+
+    a_bag->write("/data", ros::Time::now(), a_msg);
+    b_bag->write("/data", ros::Time::now(), b_msg);
+
+    swap(bag1, bag2);
+
+    bag1.close();
+    bag2.close();
+
+    swap(bag1, bag2);
+}
+
+void readBags(rosbag::CompressionType a, rosbag::CompressionType b) {
+    using std::swap;
+    rosbag::Bag bag1("/tmp/swap1.bag", rosbag::bagmode::Read);
+    rosbag::Bag bag2("/tmp/swap2.bag", rosbag::bagmode::Read);
+
+    rosbag::Bag* a_bag = &bag1;
+    rosbag::Bag* b_bag = &bag2;
+
+    swap(bag1, bag2);
+    swap(a_bag, b_bag);
+
+    // only valid when writing
+    //EXPECT_EQ(a_bag->getCompression(), a);
+    //EXPECT_EQ(b_bag->getCompression(), b);
+
+    std::vector<std::string> topics;
+    topics.push_back("data");
+
+    rosbag::View a_view(*a_bag, rosbag::TopicQuery(topics));
+    rosbag::View b_view(*b_bag, rosbag::TopicQuery(topics));
+
+    BOOST_FOREACH(rosbag::MessageInstance const m, a_view)
+    {
+        std_msgs::Int32::ConstPtr i = m.instantiate<std_msgs::Int32>();
+        ASSERT_TRUE(i);
+        EXPECT_EQ(i->data, a);
+    }
+    BOOST_FOREACH(rosbag::MessageInstance const m, b_view)
+    {
+        std_msgs::Int32::ConstPtr i = m.instantiate<std_msgs::Int32>();
+        ASSERT_TRUE(i);
+        EXPECT_EQ(i->data, b);
+    }
+}
+
+TEST(rosbag_storage, swap_bags)
+{
+    for (int i = 0; i < 3; ++i) {
+        for (int j = 0; j < 3; ++j) {
+            writeBags(rosbag::CompressionType(i), rosbag::CompressionType(j));
+            readBags(rosbag::CompressionType(i), rosbag::CompressionType(j));
+        }
+    }
+}
+
+int main(int argc, char **argv) {
+    ros::Time::init();
+
+    testing::InitGoogleTest(&argc, argv);
+    return RUN_ALL_TESTS();
+}
diff --git a/test/test_roscpp/package.xml b/test/test_roscpp/package.xml
index 52fd0e1..fe274e1 100644
--- a/test/test_roscpp/package.xml
+++ b/test/test_roscpp/package.xml
@@ -1,6 +1,6 @@
 <package>
   <name>test_roscpp</name>
-  <version>1.12.6</version>
+  <version>1.13.1</version>
   <description>
     Tests for roscpp which depend on rostest.
   </description>
diff --git a/test/test_roscpp/test/launch/spinners.xml b/test/test_roscpp/test/launch/spinners.xml
index 15650a8..0e522dc 100644
--- a/test/test_roscpp/test/launch/spinners.xml
+++ b/test/test_roscpp/test/launch/spinners.xml
@@ -1,4 +1,8 @@
 <launch>
   <test pkg="test_roscpp" type="test_roscpp-spinners" test-name="Spinners_spin" args="--gtest_filter=Spinners.spin"/>
+  <test pkg="test_roscpp" type="test_roscpp-spinners" test-name="Spinners_spinfail" args="--gtest_filter=Spinners.spinfail"/>
+  <test pkg="test_roscpp" type="test_roscpp-spinners" test-name="Spinners_singlefail" args="--gtest_filter=Spinners.singlefail"/>
   <test pkg="test_roscpp" type="test_roscpp-spinners" test-name="Spinners_multi" args="--gtest_filter=Spinners.multi"/>
+  <test pkg="test_roscpp" type="test_roscpp-spinners" test-name="Spinners_multifail" args="--gtest_filter=Spinners.multifail"/>
+  <test pkg="test_roscpp" type="test_roscpp-spinners" test-name="Spinners_async" args="--gtest_filter=Spinners.async"/>
 </launch>
diff --git a/test/test_roscpp/test/src/check_master.cpp b/test/test_roscpp/test/src/check_master.cpp
index 9b03321..4392f2b 100644
--- a/test/test_roscpp/test/src/check_master.cpp
+++ b/test/test_roscpp/test/src/check_master.cpp
@@ -40,7 +40,7 @@
 
 #include "ros/ros.h"
 
-#include "XmlRpc.h"
+#include "xmlrpcpp/XmlRpc.h"
 
 using namespace XmlRpc;
 
diff --git a/test/test_roscpp/test/src/service_call.cpp b/test/test_roscpp/test/src/service_call.cpp
index b50869a..6e05ab4 100644
--- a/test/test_roscpp/test/src/service_call.cpp
+++ b/test/test_roscpp/test/src/service_call.cpp
@@ -58,6 +58,19 @@ TEST(SrvCall, callSrv)
   ASSERT_STREQ(res.str.c_str(), "CASE_flip");
 }
 
+TEST(SrvCall, callSrvUnicode)
+{
+  test_roscpp::TestStringString::Request req;
+  test_roscpp::TestStringString::Response res;
+
+  req.str = std::string("ロボット");
+
+  ASSERT_TRUE(ros::service::waitForService("service_adv"));
+  ASSERT_TRUE(ros::service::call("service_adv", req, res));
+
+  ASSERT_STREQ(res.str.c_str(), "ロボット");
+}
+
 TEST(SrvCall, callSrvMultipleTimes)
 {
   test_roscpp::TestStringString::Request req;
diff --git a/test/test_roscpp/test/src/timer_callbacks.cpp b/test/test_roscpp/test/src/timer_callbacks.cpp
index 9f2bc7e..4f87907 100644
--- a/test/test_roscpp/test/src/timer_callbacks.cpp
+++ b/test/test_roscpp/test/src/timer_callbacks.cpp
@@ -54,6 +54,319 @@ using namespace test_roscpp;
 
 std::string g_node_name = "test_timer_callbacks";
 
+
+/************************* SteadyTimer tests **********************/
+
+class SteadyTimerHelper
+{
+  public:
+    SteadyTimerHelper(float period, bool oneshot = false)
+    : expected_period_(period)
+    , failed_(false)
+    , total_calls_(0)
+    , testing_period_(false)
+    , calls_before_testing_period_(0)
+    {
+      NodeHandle n;
+      timer_ = n.createSteadyTimer(expected_period_, &SteadyTimerHelper::callback, this, oneshot);
+    }
+
+    void callback(const SteadyTimerEvent& e)
+    {
+      bool first = last_call_.isZero();
+      SteadyTime last_call = last_call_;
+      last_call_ = SteadyTime::now();
+      SteadyTime start = last_call_;
+
+      if (!first)
+      {
+        if (fabsf(expected_next_call_.toSec() - start.toSec()) > 0.1f)
+        {
+          ROS_ERROR("Call came at wrong time (%f vs. %f)", expected_next_call_.toSec(), start.toSec());
+          failed_ = true;
+        }
+      }
+
+      if(testing_period_)
+      {
+
+        // Inside callback, less than current period, reset=false
+        if(total_calls_ == calls_before_testing_period_)
+        {
+          WallDuration p(0.5);
+          pretendWork(0.15);
+          setPeriod(p);
+        }
+
+          // Inside callback, greater than current period, reset=false
+        else if(total_calls_ == (calls_before_testing_period_+1))
+        {
+          WallDuration p(0.25);
+          pretendWork(0.15);
+          setPeriod(p);
+        }
+
+          // Inside callback, less than current period, reset=true
+        else if(total_calls_ == (calls_before_testing_period_+2))
+        {
+          WallDuration p(0.5);
+          pretendWork(0.15);
+          setPeriod(p, true);
+        }
+
+          // Inside callback, greater than current period, reset=true
+        else if(total_calls_ == (calls_before_testing_period_+3))
+        {
+          WallDuration p(0.25);
+          pretendWork(0.15);
+          setPeriod(p, true);
+        }
+      }
+      else
+      {
+        expected_next_call_ = e.current_expected + expected_period_;
+      }
+
+      SteadyTime end = SteadyTime::now();
+      last_duration_ = end - start;
+
+      ++total_calls_;
+    }
+
+    void setPeriod(const WallDuration p, bool reset=false)
+    {
+      if(reset)
+      {
+        expected_next_call_ = SteadyTime::now() + p;
+      }
+      else
+      {
+        expected_next_call_ = last_call_ + p;
+      }
+
+      timer_.setPeriod(p, reset);
+      expected_period_ = p;
+    }
+
+
+    void pretendWork(const float t)
+    {
+      ros::Rate r(1. / t);
+      r.sleep();
+    }
+
+    SteadyTime last_call_;
+    SteadyTime expected_next_call_;
+    WallDuration expected_period_;
+    WallDuration last_duration_;
+
+    bool failed_;
+
+    SteadyTimer timer_;
+    int32_t total_calls_;
+
+    bool testing_period_;
+    int  calls_before_testing_period_;
+};
+
+TEST(RoscppTimerCallbacks, singleSteadyTimeCallback)
+{
+  NodeHandle n;
+  SteadyTimerHelper helper1(0.01);
+
+  WallDuration d(0.001f);
+  for (int32_t i = 0; i < 1000 && n.ok(); ++i)
+  {
+    spinOnce();
+    d.sleep();
+  }
+
+  if (helper1.failed_)
+  {
+    FAIL();
+  }
+
+  if (helper1.total_calls_ < 99)
+  {
+    ROS_ERROR("Total calls: %d (expected at least 100)", helper1.total_calls_);
+    FAIL();
+  }
+}
+
+TEST(RoscppTimerCallbacks, multipleSteadyTimeCallbacks)
+{
+  NodeHandle n;
+  const int count = 100;
+  typedef boost::scoped_ptr<SteadyTimerHelper> HelperPtr;
+  HelperPtr helpers[count];
+  for (int i = 0; i < count; ++i)
+  {
+    helpers[i].reset(new SteadyTimerHelper((float)(i + 1) * 0.1f));
+  }
+
+  WallDuration d(0.01f);
+  const int spin_count = 1000;
+  for (int32_t i = 0; i < spin_count && n.ok(); ++i)
+  {
+    spinOnce();
+    d.sleep();
+  }
+
+  for (int i = 0; i < count; ++i)
+  {
+    if (helpers[i]->failed_)
+    {
+      ROS_ERROR("Helper %d failed", i);
+      FAIL();
+    }
+
+    int32_t expected_count = (spin_count * d.toSec()) / helpers[i]->expected_period_.toSec();
+    if (helpers[i]->total_calls_ < (expected_count - 1))
+    {
+      ROS_ERROR("Helper %d total calls: %d (at least %d expected)", i, helpers[i]->total_calls_, expected_count);
+      FAIL();
+    }
+  }
+}
+
+TEST(RoscppTimerCallbacks, steadySetPeriod)
+{
+  NodeHandle n;
+  WallDuration    period(0.5);
+  SteadyTimerHelper helper(period.toSec());
+  Rate            r(100);
+
+  // Let the callback occur once before getting started
+  while(helper.total_calls_ < 1)
+  {
+    spinOnce();
+    r.sleep();
+  }
+
+  helper.pretendWork(0.1);
+
+  // outside callback, new period < old period, reset = false
+  Duration      wait(0.5);
+  WallDuration  p(0.25);
+  helper.setPeriod(p);
+  while(helper.total_calls_ < 2)
+  {
+    spinOnce();
+    r.sleep();
+  }
+
+  helper.pretendWork(0.1);
+
+  // outside callback, new period > old period, reset = false
+  WallDuration p2(0.5);
+  helper.setPeriod(p);
+  while(helper.total_calls_ < 3)
+  {
+    spinOnce();
+    r.sleep();
+  }
+
+  helper.pretendWork(0.1);
+
+  // outside callback, new period < old period, reset = true
+  WallDuration p3(0.25);
+  helper.setPeriod(p, true);
+  while(helper.total_calls_ < 4)
+  {
+    spinOnce();
+    r.sleep();
+  }
+
+  helper.pretendWork(0.1);
+
+  // outside callback, new period > old period, reset = true
+  WallDuration p4(0.5);
+  helper.setPeriod(p, true);
+  while(helper.total_calls_ < 5)
+  {
+    spinOnce();
+    r.sleep();
+  }
+
+  // Test calling setPeriod inside callback
+  helper.calls_before_testing_period_ = helper.total_calls_;
+  int total = helper.total_calls_ + 5;
+  helper.testing_period_ = true;
+  while(helper.total_calls_ < total)
+  {
+    spinOnce();
+    r.sleep();
+  }
+  helper.testing_period_ = false;
+
+
+  if(helper.failed_)
+  {
+    ROS_ERROR("Helper failed in setPeriod");
+    FAIL();
+  }
+}
+
+TEST(RoscppTimerCallbacks, stopSteadyTimer)
+{
+  NodeHandle n;
+  SteadyTimerHelper helper(0.001);
+
+  for (int32_t i = 0; i < 1000 && n.ok(); ++i)
+  {
+    WallDuration(0.001).sleep();
+    spinOnce();
+  }
+
+  ASSERT_GT(helper.total_calls_, 0);
+  int32_t last_count = helper.total_calls_;
+  helper.timer_.stop();
+
+  for (int32_t i = 0; i < 1000 && n.ok(); ++i)
+  {
+    WallDuration(0.001).sleep();
+    spinOnce();
+  }
+
+  ASSERT_EQ(last_count, helper.total_calls_);
+}
+
+int32_t g_steady_count = 0;
+void steadyTimerCallback(const ros::SteadyTimerEvent&)
+{
+  ++g_steady_count;
+}
+
+TEST(RoscppTimerCallbacks, steadyStopThenSpin)
+{
+  g_steady_count = 0;
+  NodeHandle n;
+  ros::SteadyTimer timer = n.createSteadyTimer(ros::WallDuration(0.001), steadyTimerCallback);
+
+  WallDuration(0.1).sleep();
+  timer.stop();
+
+  spinOnce();
+
+  ASSERT_EQ(g_steady_count, 0);
+}
+
+TEST(RoscppTimerCallbacks, oneShotSteadyTimer)
+{
+  NodeHandle n;
+  SteadyTimerHelper helper(0.001, true);
+
+  for (int32_t i = 0; i < 1000 && n.ok(); ++i)
+  {
+    WallDuration(0.001).sleep();
+    spinOnce();
+  }
+
+  ASSERT_EQ(helper.total_calls_, 1);
+}
+
+/************************* WallTimer tests **********************/
+
 class WallTimerHelper
 {
 public:
diff --git a/test/test_roscpp/test/test_callback_queue.cpp b/test/test_roscpp/test/test_callback_queue.cpp
index a9cba89..8142e55 100644
--- a/test/test_roscpp/test/test_callback_queue.cpp
+++ b/test/test_roscpp/test/test_callback_queue.cpp
@@ -38,6 +38,7 @@
 #include <ros/console.h>
 #include <ros/timer.h>
 
+#include <boost/atomic.hpp>
 #include <boost/shared_ptr.hpp>
 #include <boost/bind.hpp>
 #include <boost/thread.hpp>
@@ -398,6 +399,81 @@ TEST(CallbackQueue, recursiveTimer)
   tg.join_all();
 }
 
+class ConditionObject
+{
+public:
+  ConditionObject(CallbackQueue * _queue)
+  : id(0), queue(_queue) {
+    condition_sync.store(true);
+    condition_one.store(false);
+    condition_stop.store(false);
+  }
+
+  void add();
+
+  unsigned long id;
+  CallbackQueue * queue;
+  boost::atomic<bool> condition_one;
+  boost::atomic<bool> condition_sync;
+  boost::atomic<bool> condition_stop;
+};
+
+class RaceConditionCallback : public CallbackInterface
+{
+public:
+  RaceConditionCallback(ConditionObject * _condition_object, unsigned long * _id)
+  : condition_object(_condition_object), id(_id)
+  {}
+
+  virtual CallResult call()
+  {
+    condition_object->condition_one.store(false);
+    return Success;
+  }
+
+  ConditionObject * condition_object;
+  unsigned long * id;
+};
+
+void ConditionObject::add()
+{
+  while(!condition_stop.load())
+  {
+    if(condition_sync.load())
+    {
+      condition_sync.store(false);
+      condition_one.store(true);
+      id++;
+      queue->addCallback(boost::make_shared<RaceConditionCallback>(this, &id), id);
+    }
+    boost::this_thread::sleep(boost::posix_time::microseconds(1));
+  }
+}
+
+TEST(CallbackQueue, raceConditionCallback)
+{
+  CallbackQueue queue;
+  ConditionObject condition_object(&queue);
+
+  boost::thread t(boost::bind(&ConditionObject::add, &condition_object));
+  for(unsigned int i = 0; i < 1000000; ++i)
+  {
+    if (queue.callOne() == CallbackQueue::Called)
+    {
+      if(condition_object.condition_one.load())
+      {
+        condition_object.condition_stop.store(true);
+        ASSERT_FALSE(condition_object.condition_one.load());
+      }
+    }
+
+    queue.clear();
+    condition_object.condition_sync.store(true);
+  }
+  condition_object.condition_stop.store(true);
+  t.join();
+}
+
 int main(int argc, char** argv)
 {
   testing::InitGoogleTest(&argc, argv);
diff --git a/test/test_rosgraph/package.xml b/test/test_rosgraph/package.xml
index 363dbb7..cb20a2b 100644
--- a/test/test_rosgraph/package.xml
+++ b/test/test_rosgraph/package.xml
@@ -1,6 +1,6 @@
 <package>
   <name>test_rosgraph</name>
-  <version>1.12.6</version>
+  <version>1.13.1</version>
   <description>
     Tests for rosgraph which depend on rostest.
   </description>
diff --git a/test/test_roslaunch/package.xml b/test/test_roslaunch/package.xml
index 8172738..0eb236c 100644
--- a/test/test_roslaunch/package.xml
+++ b/test/test_roslaunch/package.xml
@@ -1,6 +1,6 @@
 <package>
   <name>test_roslaunch</name>
-  <version>1.12.6</version>
+  <version>1.13.1</version>
   <description>
     Tests for roslaunch which depend on rostest.
   </description>
diff --git a/test/test_roslib_comm/package.xml b/test/test_roslib_comm/package.xml
index 41513cf..d687982 100644
--- a/test/test_roslib_comm/package.xml
+++ b/test/test_roslib_comm/package.xml
@@ -1,6 +1,6 @@
 <package>
   <name>test_roslib_comm</name>
-  <version>1.12.6</version>
+  <version>1.13.1</version>
   <description>
     Unit tests verifying that roslib is operating as expected.
   </description>
diff --git a/test/test_rosmaster/package.xml b/test/test_rosmaster/package.xml
index 12da827..d91dfb2 100644
--- a/test/test_rosmaster/package.xml
+++ b/test/test_rosmaster/package.xml
@@ -1,6 +1,6 @@
 <package>
   <name>test_rosmaster</name>
-  <version>1.12.6</version>
+  <version>1.13.1</version>
   <description>
     Tests for rosmaster which depend on rostest.
   </description>
diff --git a/test/test_rosparam/package.xml b/test/test_rosparam/package.xml
index ba45758..8d7f6fd 100644
--- a/test/test_rosparam/package.xml
+++ b/test/test_rosparam/package.xml
@@ -1,6 +1,6 @@
 <package>
   <name>test_rosparam</name>
-  <version>1.12.6</version>
+  <version>1.13.1</version>
   <description>
     A package containing the unit tests for rosparam.
   </description>
diff --git a/test/test_rospy/CMakeLists.txt b/test/test_rospy/CMakeLists.txt
index ba7d5f5..316d6ed 100644
--- a/test/test_rospy/CMakeLists.txt
+++ b/test/test_rospy/CMakeLists.txt
@@ -57,4 +57,5 @@ if(CATKIN_ENABLE_TESTING)
   add_rostest(test/rostest/latch.test)
   add_rostest(test/rostest/on_shutdown.test)
   add_rostest(test/rostest/sub_to_multiple_pubs.test)
+  add_rostest(test/rostest/latch_unsubscribe.test)
 endif()
diff --git a/tools/rosmaster/src/rosmaster/util.py b/test/test_rospy/nodes/listener_once.py
old mode 100644
new mode 100755
similarity index 63%
copy from tools/rosmaster/src/rosmaster/util.py
copy to test/test_rospy/nodes/listener_once.py
index 5b9e3d1..6d757c2
--- a/tools/rosmaster/src/rosmaster/util.py
+++ b/test/test_rospy/nodes/listener_once.py
@@ -1,8 +1,6 @@
+#!/usr/bin/env python
 # Software License Agreement (BSD License)
 #
-# Copyright (c) 2008, Willow Garage, Inc.
-# All rights reserved.
-#
 # Redistribution and use in source and binary forms, with or without
 # modification, are permitted provided that the following conditions
 # are met:
@@ -29,42 +27,27 @@
 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 # POSSIBILITY OF SUCH DAMAGE.
-#
-# Revision $Id$
 
-"""
-Utility routines for rosmaster.
-"""
+## Simple talker demo that listens to std_msgs/Strings published
+## to the 'chatter' topic and shuts down afterwards
+
+from __future__ import print_function
+
+import rospy
+from std_msgs.msg import String
+
 
-try:
-    from urllib.parse import urlparse
-except ImportError:
-    from urlparse import urlparse
-try:
-    from xmlrpc.client import ServerProxy
-except ImportError:
-    from xmlrpclib import ServerProxy
+def callback(data):
+    print(rospy.get_caller_id(), "I heard %s" % data.data)
+    rospy.signal_shutdown("Received %s, exiting now"  % data.data)
 
-from defusedxml.xmlrpc import monkey_patch
-monkey_patch()
-del monkey_patch
 
-_proxies = {} #cache ServerProxys
-def xmlrpcapi(uri):
-    """
-    @return: instance for calling remote server or None if not a valid URI
-    @rtype: xmlrpc.client.ServerProxy
-    """
-    if uri is None:
-        return None
-    uriValidate = urlparse(uri)
-    if not uriValidate[0] or not uriValidate[1]:
-        return None
-    if not uri in _proxies:
-        _proxies[uri] = ServerProxy(uri)
-    return _proxies[uri]
+def listener():
+    rospy.init_node('listener', anonymous=True)
+    rospy.sleep(rospy.get_param('delay', 0.0))
+    rospy.Subscriber("chatter", String, callback)
+    rospy.spin()
 
 
-def remove_server_proxy(uri):
-    if uri in _proxies:
-        del _proxies[uri]
+if __name__ == '__main__':
+    listener()
diff --git a/test/test_rospy/package.xml b/test/test_rospy/package.xml
index 9fe275a..e6164f1 100644
--- a/test/test_rospy/package.xml
+++ b/test/test_rospy/package.xml
@@ -1,6 +1,6 @@
 <package>
   <name>test_rospy</name>
-  <version>1.12.6</version>
+  <version>1.13.1</version>
   <description>
     rospy unit and integration test framework.
   </description>
@@ -18,6 +18,7 @@
   <build_depend>test_rosmaster</build_depend>
 
   <test_depend>python-numpy</test_depend>
+  <test_depend>python-psutil</test_depend>
   <test_depend>rosbuild</test_depend>
   <test_depend>rosgraph</test_depend>
   <test_depend>rospy</test_depend>
diff --git a/test/test_rospy/test/rostest/latch_unsubscribe.test b/test/test_rospy/test/rostest/latch_unsubscribe.test
new file mode 100644
index 0000000..b279e73
--- /dev/null
+++ b/test/test_rospy/test/rostest/latch_unsubscribe.test
@@ -0,0 +1,7 @@
+<launch>
+  <node name="listener_once_1" pkg="test_rospy" type="listener_once.py" output="screen" />
+  <node name="listener_once_2" pkg="test_rospy" type="listener_once.py" output="screen">
+    <param name="delay" value="1.0" type="double" />
+  </node>
+  <test test-name="test_latch_unsubscribe" pkg="test_rospy" type="test_latch_unsubscribe.py" />
+</launch>
diff --git a/test/test_rospy/test/rostest/test_basic_services.py b/test/test_rospy/test/rostest/test_basic_services.py
index dda4d40..847a45c 100755
--- a/test/test_rospy/test/rostest/test_basic_services.py
+++ b/test/test_rospy/test/rostest/test_basic_services.py
@@ -1,4 +1,5 @@
 #!/usr/bin/env python
+# -*- coding: utf-8 -*-
 # Software License Agreement (BSD License)
 #
 # Copyright (c) 2008, Willow Garage, Inc.
@@ -213,7 +214,21 @@ class TestBasicServicesClient(unittest.TestCase):
             resp_req_kwds = self._test_req_kwds(name, Cls, {'str': String('FOO'), 'str2': Val('bar')})
             for resp in [resp_req, resp_req_naked, resp_req_kwds]:
                 self.assertEquals('FOObar', resp.str.data)
-        
+
+    def test_String_String_unicode(self):
+        from std_msgs.msg import String
+        from test_rospy.srv import StringString, StringStringRequest
+        from test_rospy.msg import Val
+        Cls = StringString
+        Req = StringStringRequest
+
+        for name in [STRING_CAT_SERVICE_NAKED, STRING_CAT_SERVICE_WRAPPED]:
+            resp_req = self._test(name, Cls, Req(String(u'ロボット'), Val(u'机器人')))
+            resp_req_naked = self._test_req_naked(name, Cls, (String(u'ロボット'), Val(u'机器人'),))
+            resp_req_kwds = self._test_req_kwds(name, Cls, {'str': String(u'ロボット'), 'str2': Val(u'机器人')})
+            for resp in [resp_req, resp_req_naked, resp_req_kwds]:
+                self.assertEquals('ロボット机器人', resp.str.data)  # if you send in unicode, you'll receive in str
+
     def test_constants(self):
         Cls = ConstantsMultiplex
         Req = ConstantsMultiplexRequest
diff --git a/test/test_rosbag/bag_migration_tests/scripts/generate_data_3.py b/test/test_rospy/test/rostest/test_latch_unsubscribe.py
similarity index 50%
copy from test/test_rosbag/bag_migration_tests/scripts/generate_data_3.py
copy to test/test_rospy/test/rostest/test_latch_unsubscribe.py
index b359384..f75ed33 100755
--- a/test/test_rosbag/bag_migration_tests/scripts/generate_data_3.py
+++ b/test/test_rospy/test/rostest/test_latch_unsubscribe.py
@@ -1,9 +1,6 @@
 #!/usr/bin/env python
 # Software License Agreement (BSD License)
 #
-# Copyright (c) 2008, Willow Garage, Inc.
-# All rights reserved.
-#
 # Redistribution and use in source and binary forms, with or without
 # modification, are permitted provided that the following conditions
 # are met:
@@ -31,41 +28,56 @@
 # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 # POSSIBILITY OF SUCH DAMAGE.
 
-import rospy
-from test_rosbag.msg import *
+PKG = 'test_rospy'
+NAME = 'test_latch_unsubscribe'
+
+import os
+import sys
+import unittest
+
+import psutil
+
+from std_msgs.msg import String
+
+
+def _get_connections(process_info):
+    if hasattr(process_info, 'connections'):  # new naming
+        return process_info.connections()
+    elif hasattr(process_info, 'get_connections'):  # old naming
+        return process_info.get_connections()
+    raise AttributeError('Wrong psutil version?')
+
+
+def _get_connection_statii(process_info):
+    return (conn.status for conn in _get_connections(process_info))
 
-import rosbag
 
-def generate_data():
-    bag = rosbag.Bag("test/migrated_explicit_gen3.bag", "w")
-    m = MigratedExplicit(None, 17, 58.2, "aldfkja", 82)
-    bag.write("migrated_explicit", m, genpy.Time())
-    bag.close()
+class TestLatch(unittest.TestCase):
 
-    bag = rosbag.Bag("test/migrated_implicit_gen3.bag", "w")
-    m = MigratedImplicit(None, MigratedExplicit(None, 17, 58.2, "aldfkja", 82), "kljene", 16.32, 34)
-    bag.write("migrated_implicit", m, genpy.Time())
-    bag.close()
+    def setUp(self):
+        pass
 
-    bag = rosbag.Bag("test/migrated_mixed_gen3.bag", "w")
-    m = MigratedMixed(None, MigratedImplicit(None, MigratedExplicit(None, 17, 58.2, "aldfkja", 82), "kljene", 16.32, 34), 59)
-    bag.write("migrated_mixed", m, genpy.Time())
-    bag.close()
+    def test_latch(self):
+        import rospy
+        proc_info = psutil.Process(os.getpid())
+        self.assertNotIn('CLOSE_WAIT', _get_connection_statii(proc_info),
+                         'CLOSE_WAIT sockets already before the test. This '
+                         'should not happen at all.')
 
-    bag = rosbag.Bag("test/partially_migrated_gen3.bag", "w")
-    m = PartiallyMigrated(40, MigratedExplicit(None, 17, 58.2, "aldfkja", 82), "radasdk")
-    bag.write("partially_migrated", m, genpy.Time())
-    bag.close()
+        rospy.init_node(NAME)
+        pub = rospy.Publisher('chatter', String, latch=True)
+        pub.publish(String("hello"))
+        rospy.sleep(0.5)
+        self.assertNotIn('CLOSE_WAIT', _get_connection_statii(proc_info),
+                         'CLOSE_WAIT sockets after the subscriber exited. '
+                         '(#107)')
+        rospy.sleep(1.5)
+        # also check for a second subscriber
+        self.assertNotIn('CLOSE_WAIT', _get_connection_statii(proc_info),
+                         'CLOSE_WAIT sockets after the second subscriber '
+                         'exited. (#107)')
 
-    bag = rosbag.Bag("test/renamed_gen3.bag", "w")
-    m = Renamed3(2.17, [8, 2, 5, 1])
-    bag.write("renamed", m, genpy.Time())
-    bag.close()
 
-    bag = rosbag.Bag("test/converged_gen3.bag", "w")
-    m = Converged([1.2, 3.4, 5.6, 7.8], [SimpleMigrated(11), SimpleMigrated(22), SimpleMigrated(33), SimpleMigrated(44)])
-    bag.write("converged", m, genpy.Time())
-    bag.close()
-        
 if __name__ == '__main__':
-    generate_data()
+    import rostest
+    rostest.run(PKG, NAME, TestLatch, sys.argv)
diff --git a/test/test_rospy/test/rostest/test_rospy_client_online.py b/test/test_rospy/test/rostest/test_rospy_client_online.py
index 028313d..4000ed6 100755
--- a/test/test_rospy/test/rostest/test_rospy_client_online.py
+++ b/test/test_rospy/test/rostest/test_rospy_client_online.py
@@ -101,6 +101,39 @@ class TestRospyClientOnline(unittest.TestCase):
             self.assert_("[FATAL]" in sys.stderr.getvalue())            
             self.assert_("test 4" in sys.stderr.getvalue())            
 
+            # logXXX_once
+            for i in range(3):
+                sys.stdout = StringIO()
+                rospy.loginfo_once("test 1")
+                if i == 0:
+                    self.assert_("test 1" in sys.stdout.getvalue())
+                else:
+                    self.assert_("" == sys.stdout.getvalue())
+
+            for i in range(3):
+                sys.stderr = StringIO()
+                rospy.logwarn_once("test 2")
+                if i == 0:
+                    self.assert_("test 2" in sys.stderr.getvalue())
+                else:
+                    self.assert_("" == sys.stderr.getvalue())
+
+            for i in range(3):
+                sys.stderr = StringIO()
+                rospy.logerr_once("test 3")
+                if i == 0:
+                    self.assert_("test 3" in sys.stderr.getvalue())
+                else:
+                    self.assert_("" == sys.stderr.getvalue())
+
+            for i in range(3):
+                sys.stderr = StringIO()
+                rospy.logfatal_once("test 4")
+                if i == 0:
+                    self.assert_("test 4" in sys.stderr.getvalue())
+                else:
+                    self.assert_("" == sys.stderr.getvalue())
+
             # logXXX_throttle
             for i in range(3):
                 sys.stdout = StringIO()
@@ -149,6 +182,24 @@ class TestRospyClientOnline(unittest.TestCase):
                     rospy.sleep(rospy.Duration(2))
                 else:
                     self.assert_("test 4" in sys.stderr.getvalue())
+            
+            rospy.loginfo("test child logger 1", logger_name="log1")
+            self.assert_("test child logger 1" in sys.stdout.getvalue())
+            
+            rospy.logwarn("test child logger 2", logger_name="log2")            
+            self.assert_("[WARN]" in sys.stderr.getvalue())
+            self.assert_("test child logger 2" in sys.stderr.getvalue())
+
+            sys.stderr = StringIO()
+            rospy.logerr("test child logger 3", logger_name="log3")            
+            self.assert_("[ERROR]" in sys.stderr.getvalue())
+            self.assert_("test child logger 3" in sys.stderr.getvalue())
+            
+            sys.stderr = StringIO()
+            rospy.logfatal("test child logger 4", logger_name="log4")            
+            self.assert_("[FATAL]" in sys.stderr.getvalue())            
+            self.assert_("test child logger 4" in sys.stderr.getvalue()) 
+
         finally:
             sys.stdout = real_stdout
             sys.stderr = real_stderr
diff --git a/test/test_rospy/test/unit/test_rospy_api.py b/test/test_rospy/test/unit/test_rospy_api.py
index fe541d8..4141aa4 100644
--- a/test/test_rospy/test/unit/test_rospy_api.py
+++ b/test/test_rospy/test/unit/test_rospy_api.py
@@ -123,6 +123,11 @@ class TestRospyApi(unittest.TestCase):
         rospy.logfatal_throttle
         rospy.loginfo_throttle
         rospy.logwarn_throttle
+        rospy.logdebug_once
+        rospy.logerr_once
+        rospy.logfatal_once
+        rospy.loginfo_once
+        rospy.logwarn_once
         rospy.myargv
         rospy.on_shutdown
         rospy.parse_rosrpc_uri
diff --git a/test/test_rospy/test/unit/test_rospy_core.py b/test/test_rospy/test/unit/test_rospy_core.py
index bb0375a..d1889b8 100644
--- a/test/test_rospy/test/unit/test_rospy_core.py
+++ b/test/test_rospy/test/unit/test_rospy_core.py
@@ -79,7 +79,13 @@ class TestRospyCore(unittest.TestCase):
         rospy.logout('out')
         rospy.logerr('err')
         rospy.logfatal('fatal')
-        
+        #basic named logger test
+        rospy.logdebug('debug', logger_name="child1")
+        rospy.logwarn('warn', logger_name="child1")
+        rospy.logout('out', logger_name="child1")
+        rospy.logerr('err', logger_name="child1")
+        rospy.logfatal('fatal', logger_name="child1")
+
     def test_add_shutdown_hook(self):
         def handle(reason):
             pass
diff --git a/test/test_rospy/test/unit/test_rospy_tcpros_base.py b/test/test_rospy/test/unit/test_rospy_tcpros_base.py
index b2544e8..e199436 100644
--- a/test/test_rospy/test/unit/test_rospy_tcpros_base.py
+++ b/test/test_rospy/test/unit/test_rospy_tcpros_base.py
@@ -154,8 +154,8 @@ class TestRospyTcprosBase(unittest.TestCase):
         self.assertEquals('TCPROS', t.transport_type)        
         self.assertEquals(OUTBOUND, t.direction)        
         self.assertEquals('unknown', t.endpoint_id)        
-        self.assertEquals('', t.read_buff.getvalue())
-        self.assertEquals('', t.write_buff.getvalue())
+        self.assertEquals(b'', t.read_buff.getvalue())
+        self.assertEquals(b'', t.write_buff.getvalue())
 
         s = MockSock('12345')
         t.set_socket(s, 'new_endpoint_id')
diff --git a/test/test_rospy/test/unit/test_rospy_tcpros_pubsub.py b/test/test_rospy/test/unit/test_rospy_tcpros_pubsub.py
index 7bd2bbb..f7e805e 100644
--- a/test/test_rospy/test/unit/test_rospy_tcpros_pubsub.py
+++ b/test/test_rospy/test/unit/test_rospy_tcpros_pubsub.py
@@ -40,7 +40,7 @@ import time
 
 class FakeSocket(object):
     def __init__(self):
-        self.data = ''
+        self.data = b''
         self.sockopt = None
     def fileno(self):
         # fool select logic by giving it stdout fileno
diff --git a/test/test_rospy/test/unit/test_rospy_topics.py b/test/test_rospy/test/unit/test_rospy_topics.py
index 14a45d2..e3b31f2 100644
--- a/test/test_rospy/test/unit/test_rospy_topics.py
+++ b/test/test_rospy/test/unit/test_rospy_topics.py
@@ -138,7 +138,7 @@ class TestRospyTopics(unittest.TestCase):
         self.assertEquals(None, impl.latch)                
         self.assertEquals(0, impl.seq)
         self.assertEquals(1, impl.ref_count)
-        self.assertEquals('', impl.buff.getvalue())
+        self.assertEquals(b'', impl.buff.getvalue())
         self.failIf(impl.closed)
         self.failIf(impl.has_connections())
         # check publish() fall-through
diff --git a/test/test_rosservice/package.xml b/test/test_rosservice/package.xml
index f790c24..61cc0a0 100644
--- a/test/test_rosservice/package.xml
+++ b/test/test_rosservice/package.xml
@@ -1,6 +1,6 @@
 <package>
   <name>test_rosservice</name>
-  <version>1.12.6</version>
+  <version>1.13.1</version>
   <description>
     Tests for the rosservice tool.
   </description>
diff --git a/test/test_rosservice/test/check_rosservice_command_line_online.py b/test/test_rosservice/test/check_rosservice_command_line_online.py
index 1ae3f00..dc696ad 100755
--- a/test/test_rosservice/test/check_rosservice_command_line_online.py
+++ b/test/test_rosservice/test/check_rosservice_command_line_online.py
@@ -88,28 +88,28 @@ class TestRosserviceOnline(unittest.TestCase):
         for name in names:
             # args
             output = Popen([cmd, 'args', name], stdout=PIPE).communicate()[0]
-            self.assertEquals('a b', output.strip())
+            self.assertEquals(b'a b', output.strip())
 
             # type
             output = Popen([cmd, 'type', name], stdout=PIPE).communicate()[0]
-            self.assertEquals('test_rosmaster/AddTwoInts', output.strip())
+            self.assertEquals(b'test_rosmaster/AddTwoInts', output.strip())
 
             # find
             output = Popen([cmd, 'find', 'test_rosmaster/AddTwoInts'], stdout=PIPE).communicate()[0]
-            values = [v.strip() for v in output.split('\n') if v.strip()]
+            values = [v.strip() for v in output.decode().split('\n') if v.strip()]
             self.assertEquals(set(values), set(services))
 
             # uri
             output = Popen([cmd, 'uri', name], stdout=PIPE).communicate()[0]
             # - no exact answer
-            self.assert_(output.startswith('rosrpc://'), output)
+            self.assert_(output.decode().startswith('rosrpc://'), output)
 
             # call
             output = Popen([cmd, 'call', '--wait', name, '1', '2'], stdout=PIPE).communicate()[0]
-            self.assertEquals('sum: 3', output.strip())
+            self.assertEquals(b'sum: 3', output.strip())
 
             output = Popen([cmd, 'call', name, '1', '2'], stdout=PIPE).communicate()[0]
-            self.assertEquals('sum: 3', output.strip())
+            self.assertEquals(b'sum: 3', output.strip())
 
         name = 'header_echo'
         # test with a Header so we can validate keyword args
@@ -143,13 +143,13 @@ class TestRosserviceOnline(unittest.TestCase):
         env['ROS_NAMESPACE'] = 'foo'
         uri1 = Popen([cmd, 'uri', 'add_two_ints'], stdout=PIPE).communicate()[0]
         uri2 = Popen([cmd, 'uri', 'add_two_ints'], env=env, stdout=PIPE).communicate()[0]
-        self.assert_(uri2.startswith('rosrpc://'))
+        self.assert_(uri2.decode().startswith('rosrpc://'))
         self.assertNotEquals(uri1, uri2)
 
         # test_call_wait
         def task1():
             output = Popen([cmd, 'call', '--wait', 'wait_two_ints', '1', '2'], stdout=PIPE).communicate()[0]
-            self.assertEquals('sum: 3', output.strip())
+            self.assertEquals(b'sum: 3', output.strip())
         timeout_t = time.time() + 5.
         t1 = TestTask(task1)
         t1.start()
diff --git a/test/test_rostopic/package.xml b/test/test_rostopic/package.xml
index c1718d3..c7851a3 100644
--- a/test/test_rostopic/package.xml
+++ b/test/test_rostopic/package.xml
@@ -1,6 +1,6 @@
 <package>
   <name>test_rostopic</name>
-  <version>1.12.6</version>
+  <version>1.13.1</version>
   <description>
     Tests for rostopic.
   </description>
diff --git a/tools/rosbag/CHANGELOG.rst b/tools/rosbag/CHANGELOG.rst
index 59bd38e..099712b 100644
--- a/tools/rosbag/CHANGELOG.rst
+++ b/tools/rosbag/CHANGELOG.rst
@@ -2,6 +2,26 @@
 Changelog for package rosbag
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
+1.13.1 (2017-07-27)
+-------------------
+* fix handling connections without indices (`#1109 <https://github.com/ros/ros_comm/pull/1109>`_)
+* improve message of check command (`#1067 <https://github.com/ros/ros_comm/pull/1067>`_)
+* fix BZip2 inclusion (`#1016 <https://github.com/ros/ros_comm/pull/1016>`_)
+* expose rate-control-topic and rate-control-max-delay args to command line tool (`#1015 <https://github.com/ros/ros_comm/pull/1015>`_)
+* improve migration rule generation (`#1009 <https://github.com/ros/ros_comm/pull/1009>`_, `#1010 <https://github.com/ros/ros_comm/pull/1010>`_, `#1011 <https://github.com/ros/ros_comm/pull/1011>`_)
+
+1.13.0 (2017-02-22)
+-------------------
+
+1.12.7 (2017-02-17)
+-------------------
+* throw exception instead of accessing invalid memory (`#971 <https://github.com/ros/ros_comm/pull/971>`_)
+* move headers to include/xmlrpcpp (`#962 <https://github.com/ros/ros_comm/issues/962>`_)
+* added option wait-for-subscriber to rosbag play (`#959 <https://github.com/ros/ros_comm/issues/959>`_)
+* terminate underlying rosbag play, record  on SIGTERM (`#951 <https://github.com/ros/ros_comm/issues/951>`_)
+* add pause service for rosbag player (`#949 <https://github.com/ros/ros_comm/issues/949>`_)
+* add rate-control-topic and rate-control-max-delay. (`#947 <https://github.com/ros/ros_comm/issues/947>`_)
+
 1.12.6 (2016-10-26)
 -------------------
 * fix BagMigrationException in migrate_raw (`#917 <https://github.com/ros/ros_comm/issues/917>`_)
diff --git a/tools/rosbag/CMakeLists.txt b/tools/rosbag/CMakeLists.txt
index 8656ac3..286b14f 100644
--- a/tools/rosbag/CMakeLists.txt
+++ b/tools/rosbag/CMakeLists.txt
@@ -5,7 +5,7 @@ if(NOT WIN32)
   set_directory_properties(PROPERTIES COMPILE_OPTIONS "-Wall;-Wextra")
 endif()
 
-find_package(catkin REQUIRED COMPONENTS rosbag_storage rosconsole roscpp topic_tools xmlrpcpp)
+find_package(catkin REQUIRED COMPONENTS rosbag_storage rosconsole roscpp std_srvs topic_tools xmlrpcpp)
 find_package(Boost REQUIRED COMPONENTS date_time regex program_options filesystem)
 find_package(BZip2 REQUIRED)
 
@@ -14,19 +14,23 @@ catkin_python_setup()
 # Support large bags (>2GB) on 32-bit systems
 add_definitions(-D_FILE_OFFSET_BITS=64)
 
-include_directories(include ${catkin_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS})
+include_directories(include ${catkin_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS}
+  ${BZIP2_INCLUDE_DIR}
+)
 
 catkin_package(
   LIBRARIES rosbag
   INCLUDE_DIRS include
-  CATKIN_DEPENDS rosbag_storage rosconsole roscpp topic_tools xmlrpcpp)
+  CATKIN_DEPENDS rosbag_storage rosconsole roscpp std_srvs topic_tools xmlrpcpp)
 
 add_library(rosbag
   src/player.cpp
   src/recorder.cpp
   src/time_translator.cpp)
 
-target_link_libraries(rosbag ${catkin_LIBRARIES} ${Boost_LIBRARIES})
+target_link_libraries(rosbag ${catkin_LIBRARIES} ${Boost_LIBRARIES}
+  ${BZIP2_LIBRARIES}
+)
 
 add_executable(record src/record.cpp)
 target_link_libraries(record rosbag)
@@ -58,3 +62,7 @@ catkin_install_python(PROGRAMS
   scripts/savemsg.py
   scripts/topic_renamer.py
   DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION})
+
+if(CATKIN_ENABLE_TESTING)
+  catkin_add_nosetests(test)
+endif()
diff --git a/tools/rosbag/include/rosbag/player.h b/tools/rosbag/include/rosbag/player.h
index 3cb307b..09dd897 100644
--- a/tools/rosbag/include/rosbag/player.h
+++ b/tools/rosbag/include/rosbag/player.h
@@ -47,9 +47,12 @@
 
 #include <ros/ros.h>
 #include <ros/time.h>
+#include <std_srvs/SetBool.h>
 
 #include "rosbag/bag.h"
 
+#include <topic_tools/shape_shifter.h>
+
 #include "rosbag/time_translator.h"
 #include "rosbag/macros.h"
 
@@ -88,6 +91,9 @@ struct ROSBAG_DECL PlayerOptions
     bool     has_duration;
     float    duration;
     bool     keep_alive;
+    bool     wait_for_subscribers;
+    std::string rate_control_topic;
+    float    rate_control_max_delay;
     ros::Duration skip_empty;
 
     std::vector<std::string> bags;
@@ -171,27 +177,45 @@ private:
     void setupTerminal();
     void restoreTerminal();
 
+    void updateRateTopicTime(const ros::MessageEvent<topic_tools::ShapeShifter const>& msg_event);
+
     void doPublish(rosbag::MessageInstance const& m);
 
     void doKeepAlive();
 
     void printTime();
 
+    bool pauseCallback(std_srvs::SetBool::Request &req, std_srvs::SetBool::Response &res);
+
+    void processPause(const bool paused, ros::WallTime &horizon);
+
+    void waitForSubscribers() const;
 
 private:
+    typedef std::map<std::string, ros::Publisher> PublisherMap;
 
     PlayerOptions options_;
 
     ros::NodeHandle node_handle_;
 
+    ros::ServiceServer pause_service_;
+
     bool paused_;
+    bool delayed_;
 
     bool pause_for_topics_;
 
+    bool pause_change_requested_;
+
+    bool requested_pause_state_;
+
+    ros::Subscriber rate_control_sub_;
+    ros::Time last_rate_control_;
+
     ros::WallTime paused_time_;
 
     std::vector<boost::shared_ptr<Bag> >  bags_;
-    std::map<std::string, ros::Publisher> publishers_;
+    PublisherMap publishers_;
 
     // Terminal
     bool    terminal_modified_;
diff --git a/tools/rosbag/package.xml b/tools/rosbag/package.xml
index bad816c..fc848dc 100644
--- a/tools/rosbag/package.xml
+++ b/tools/rosbag/package.xml
@@ -1,6 +1,6 @@
 <package>
   <name>rosbag</name>
-  <version>1.12.6</version>
+  <version>1.13.1</version>
   <description>
     This is a set of tools for recording from and playing back to ROS
     topics.  It is intended to be high performance and avoids
@@ -23,6 +23,7 @@
   <build_depend>rosconsole</build_depend>
   <build_depend>roscpp</build_depend>
   <build_depend>roscpp_serialization</build_depend>
+  <build_depend>std_srvs</build_depend>
   <build_depend>topic_tools</build_depend>
   <build_depend>xmlrpcpp</build_depend>
 
@@ -35,6 +36,7 @@
   <run_depend>roscpp</run_depend>
   <run_depend>roslib</run_depend>
   <run_depend>rospy</run_depend>
+  <run_depend>std_srvs</run_depend>
   <run_depend>topic_tools</run_depend>
   <run_depend>xmlrpcpp</run_depend>
 
diff --git a/tools/rosbag/src/play.cpp b/tools/rosbag/src/play.cpp
index ccca080..ed5ddb3 100644
--- a/tools/rosbag/src/play.cpp
+++ b/tools/rosbag/src/play.cpp
@@ -61,8 +61,12 @@ rosbag::PlayerOptions parseOptions(int argc, char** argv) {
       ("try-future-version", "still try to open a bag file, even if the version is not known to the player")
       ("topics", po::value< std::vector<std::string> >()->multitoken(), "topics to play back")
       ("pause-topics", po::value< std::vector<std::string> >()->multitoken(), "topics to pause playback on")
-      ("bags", po::value< std::vector<std::string> >(), "bag files to play back from");
-    
+      ("bags", po::value< std::vector<std::string> >(), "bag files to play back from")
+      ("wait-for-subscribers", "wait for at least one subscriber on each topic before publishing")
+      ("rate-control-topic", po::value<std::string>(), "watch the given topic, and if the last publish was more than <rate-control-max-delay> ago, wait until the topic publishes again to continue playback")
+      ("rate-control-max-delay", po::value<float>()->default_value(1.0f), "maximum time difference from <rate-control-topic> before pausing")
+      ;
+
     po::positional_options_description p;
     p.add("bags", -1);
     
@@ -118,6 +122,8 @@ rosbag::PlayerOptions parseOptions(int argc, char** argv) {
       opts.loop = true;
     if (vm.count("keep-alive"))
       opts.keep_alive = true;
+    if (vm.count("wait-for-subscribers"))
+      opts.wait_for_subscribers = true;
 
     if (vm.count("topics"))
     {
@@ -137,6 +143,12 @@ rosbag::PlayerOptions parseOptions(int argc, char** argv) {
         opts.pause_topics.push_back(*i);
     }
 
+    if (vm.count("rate-control-topic"))
+      opts.rate_control_topic = vm["rate-control-topic"].as<std::string>();
+
+    if (vm.count("rate-control-max-delay"))
+      opts.rate_control_max_delay = vm["rate-control-max-delay"].as<float>();
+
     if (vm.count("bags"))
     {
       std::vector<std::string> bags = vm["bags"].as< std::vector<std::string> >();
diff --git a/tools/rosbag/src/player.cpp b/tools/rosbag/src/player.cpp
index dd29341..32570bd 100644
--- a/tools/rosbag/src/player.cpp
+++ b/tools/rosbag/src/player.cpp
@@ -87,6 +87,9 @@ PlayerOptions::PlayerOptions() :
     has_duration(false),
     duration(0.0f),
     keep_alive(false),
+    wait_for_subscribers(false),
+    rate_control_topic(""),
+    rate_control_max_delay(1.0f),
     skip_empty(ros::DURATION_MAX)
 {
 }
@@ -106,8 +109,12 @@ Player::Player(PlayerOptions const& options) :
     // If we were given a list of topics to pause on, then go into that mode
     // by default (it can be toggled later via 't' from the keyboard).
     pause_for_topics_(options_.pause_topics.size() > 0),
+    pause_change_requested_(false),
+    requested_pause_state_(false),
     terminal_modified_(false)
 {
+  ros::NodeHandle private_node_handle("~");
+  pause_service_ = private_node_handle.advertiseService("pause_playback", &Player::pauseCallback, this);
 }
 
 Player::~Player() {
@@ -203,6 +210,26 @@ void Player::publish() {
         }
     }
 
+    if (options_.rate_control_topic != "")
+    {
+        std::cout << "Creating rate control topic subscriber..." << std::flush;
+
+        boost::shared_ptr<ros::Subscriber> sub(boost::make_shared<ros::Subscriber>());
+        ros::SubscribeOptions ops;
+        ops.topic = options_.rate_control_topic;
+        ops.queue_size = 10;
+        ops.md5sum = ros::message_traits::md5sum<topic_tools::ShapeShifter>();
+        ops.datatype = ros::message_traits::datatype<topic_tools::ShapeShifter>();
+        ops.helper = boost::make_shared<ros::SubscriptionCallbackHelperT<
+            const ros::MessageEvent<topic_tools::ShapeShifter const> &> >(
+                boost::bind(&Player::updateRateTopicTime, this, _1));
+
+        rate_control_sub_ = node_handle_.subscribe(ops);
+
+        std::cout << " done." << std::endl;
+    }
+
+
     std::cout << "Waiting " << options_.advertise_sleep.toSec() << " seconds after advertising topics..." << std::flush;
     options_.advertise_sleep.sleep();
     std::cout << " done." << std::endl;
@@ -211,6 +238,11 @@ void Player::publish() {
 
     paused_ = options_.start_paused;
 
+    if (options_.wait_for_subscribers)
+    {
+        waitForSubscribers();
+    }
+
     while (true) {
         // Set up our time_translator and publishers
 
@@ -220,6 +252,9 @@ void Player::publish() {
         time_translator_.setRealStartTime(start_time_);
         bag_length_ = view.getEndTime() - view.getBeginTime();
 
+        // Set the last rate control to now, so the program doesn't start delayed.
+        last_rate_control_ = start_time_;
+
         time_publisher_.setTime(start_time_);
 
         ros::WallTime now_wt = ros::WallTime::now();
@@ -259,6 +294,42 @@ void Player::publish() {
     ros::shutdown();
 }
 
+void Player::updateRateTopicTime(const ros::MessageEvent<topic_tools::ShapeShifter const>& msg_event)
+{
+    boost::shared_ptr<topic_tools::ShapeShifter const> const &ssmsg = msg_event.getConstMessage();
+    std::string def = ssmsg->getMessageDefinition();
+    size_t length = ros::serialization::serializationLength(*ssmsg);
+    
+    // Check the message definition.
+    std::istringstream f(def);
+    std::string s;
+    bool flag = false;
+    while(std::getline(f, s, '\n')) {
+        if (s.find("#") != 0) {
+            // Does not start with #, is not a comment.
+            if(s == "Header header") {
+                flag = true;
+            }
+        }
+    }
+    // If the header is not the first element in the message according to the definition, throw an error.
+    if (!flag) {
+        std::cout << std::endl << "WARNING: Rate control topic is bad, header is not first. MSG may be malformed." << std::endl;
+        return;
+    }
+
+    std::vector<uint8_t> buffer(length);
+    ros::serialization::OStream ostream(&buffer[0], length);
+    ros::serialization::Serializer<topic_tools::ShapeShifter>::write(ostream, *ssmsg);
+
+    // Assuming that the header is the first several bytes of the message.
+    //uint32_t header_sequence_id   = buffer[0] | (uint32_t)buffer[1] << 8 | (uint32_t)buffer[2] << 16 | (uint32_t)buffer[3] << 24;
+    int32_t header_timestamp_sec  = buffer[4] | (uint32_t)buffer[5] << 8 | (uint32_t)buffer[6] << 16 | (uint32_t)buffer[7] << 24;
+    int32_t header_timestamp_nsec = buffer[8] | (uint32_t)buffer[9] << 8 | (uint32_t)buffer[10] << 16 | (uint32_t)buffer[11] << 24;
+
+    last_rate_control_ = ros::Time(header_timestamp_sec, header_timestamp_nsec);
+}
+
 void Player::printTime()
 {
     if (!options_.quiet) {
@@ -266,18 +337,78 @@ void Player::printTime()
         ros::Time current_time = time_publisher_.getTime();
         ros::Duration d = current_time - start_time_;
 
+
         if (paused_)
         {
-            printf("\r [PAUSED]   Bag Time: %13.6f   Duration: %.6f / %.6f     \r", time_publisher_.getTime().toSec(), d.toSec(), bag_length_.toSec());
+            printf("\r [PAUSED ]  Bag Time: %13.6f   Duration: %.6f / %.6f               \r", time_publisher_.getTime().toSec(), d.toSec(), bag_length_.toSec());
+        }
+        else if (delayed_)
+        {
+            ros::Duration time_since_rate = std::max(ros::Time::now() - last_rate_control_, ros::Duration(0));
+            printf("\r [DELAYED]  Bag Time: %13.6f   Duration: %.6f / %.6f   Delay: %.2f \r", time_publisher_.getTime().toSec(), d.toSec(), bag_length_.toSec(), time_since_rate.toSec());
         }
         else
         {
-            printf("\r [RUNNING]  Bag Time: %13.6f   Duration: %.6f / %.6f     \r", time_publisher_.getTime().toSec(), d.toSec(), bag_length_.toSec());
+            printf("\r [RUNNING]  Bag Time: %13.6f   Duration: %.6f / %.6f               \r", time_publisher_.getTime().toSec(), d.toSec(), bag_length_.toSec());
         }
         fflush(stdout);
     }
 }
 
+bool Player::pauseCallback(std_srvs::SetBool::Request &req, std_srvs::SetBool::Response &res)
+{
+  pause_change_requested_ = (req.data != paused_);
+  requested_pause_state_ = req.data;
+
+  res.success = pause_change_requested_;
+
+  if (res.success)
+  {
+    res.message = std::string("Playback is now ") + (requested_pause_state_ ? "paused" : "resumed");
+  }
+  else
+  {
+    res.message = std::string("Bag is already ") + (requested_pause_state_ ? "paused." : "running.");
+  }
+
+  return true;
+}
+
+void Player::processPause(const bool paused, ros::WallTime &horizon)
+{
+  paused_ = paused;
+
+  if (paused_)
+  {
+    paused_time_ = ros::WallTime::now();
+  }
+  else
+  {
+    // Make sure time doesn't shift after leaving pause.
+    ros::WallDuration shift = ros::WallTime::now() - paused_time_;
+    paused_time_ = ros::WallTime::now();
+
+    time_translator_.shift(ros::Duration(shift.sec, shift.nsec));
+
+    horizon += shift;
+    time_publisher_.setWCHorizon(horizon);
+  }
+}
+
+void Player::waitForSubscribers() const
+{
+    bool all_topics_subscribed = false;
+    std::cout << "Waiting for subscribers." << std::endl;
+    while (!all_topics_subscribed) {
+        all_topics_subscribed = true;
+        foreach(const PublisherMap::value_type& pub, publishers_) {
+            all_topics_subscribed &= pub.second.getNumSubscribers() > 0;
+        }
+        ros::Duration(0.1).sleep();
+    }
+    std::cout << "Finished waiting for subscribers." << std::endl;
+}
+
 void Player::doPublish(MessageInstance const& m) {
     string const& topic   = m.getTopic();
     ros::Time const& time = m.getTime();
@@ -294,6 +425,9 @@ void Player::doPublish(MessageInstance const& m) {
     map<string, ros::Publisher>::iterator pub_iter = publishers_.find(callerid_topic);
     ROS_ASSERT(pub_iter != publishers_.end());
 
+    // Update subscribers.
+    ros::spinOnce();
+
     // If immediate specified, play immediately
     if (options_.at_once) {
         time_publisher_.stepClock();
@@ -330,27 +464,31 @@ void Player::doPublish(MessageInstance const& m) {
         }
     }
 
-    while ((paused_ || !time_publisher_.horizonReached()) && node_handle_.ok())
+    // Check if the rate control topic has posted recently enough to continue, or if a delay is needed.
+    // Delayed is separated from paused to allow more verbose printing.
+    if (rate_control_sub_ != NULL) {
+        if ((time_publisher_.getTime() - last_rate_control_).toSec() > options_.rate_control_max_delay) {
+            delayed_ = true;
+            paused_time_ = ros::WallTime::now();
+        }
+    }
+
+    while ((paused_ || delayed_ || !time_publisher_.horizonReached()) && node_handle_.ok())
     {
         bool charsleftorpaused = true;
         while (charsleftorpaused && node_handle_.ok())
         {
+            ros::spinOnce();
+
+            if (pause_change_requested_)
+            {
+              processPause(requested_pause_state_, horizon);
+              pause_change_requested_ = false;
+            }
+
             switch (readCharFromStdin()){
             case ' ':
-                paused_ = !paused_;
-                if (paused_) {
-                    paused_time_ = ros::WallTime::now();
-                }
-                else
-                {
-                    ros::WallDuration shift = ros::WallTime::now() - paused_time_;
-                    paused_time_ = ros::WallTime::now();
-         
-                    time_translator_.shift(ros::Duration(shift.sec, shift.nsec));
-
-                    horizon += shift;
-                    time_publisher_.setWCHorizon(horizon);
-                }
+                processPause(!paused_, horizon);
                 break;
             case 's':
                 if (paused_) {
@@ -378,6 +516,25 @@ void Player::doPublish(MessageInstance const& m) {
                 {
                     printTime();
                     time_publisher_.runStalledClock(ros::WallDuration(.1));
+                    ros::spinOnce();
+                }
+                else if (delayed_)
+                {
+                    printTime();
+                    time_publisher_.runStalledClock(ros::WallDuration(.1));
+                    ros::spinOnce();
+                    // You need to check the rate here too.
+                    if(rate_control_sub_ == NULL || (time_publisher_.getTime() - last_rate_control_).toSec() <= options_.rate_control_max_delay) {
+                        delayed_ = false;
+                        // Make sure time doesn't shift after leaving delay.
+                        ros::WallDuration shift = ros::WallTime::now() - paused_time_;
+                        paused_time_ = ros::WallTime::now();
+         
+                        time_translator_.shift(ros::Duration(shift.sec, shift.nsec));
+
+                        horizon += shift;
+                        time_publisher_.setWCHorizon(horizon);
+                    }
                 }
                 else
                     charsleftorpaused = false;
@@ -386,6 +543,7 @@ void Player::doPublish(MessageInstance const& m) {
 
         printTime();
         time_publisher_.runClock(ros::WallDuration(.1));
+        ros::spinOnce();
     }
 
     pub_iter->second.publish(m);
@@ -406,6 +564,9 @@ void Player::doKeepAlive() {
         return;
     }
 
+    // If we're done and just staying alive, don't watch the rate control topic. We aren't publishing anyway.
+    delayed_ = false;
+
     while ((paused_ || !time_publisher_.horizonReached()) && node_handle_.ok())
     {
         bool charsleftorpaused = true;
@@ -419,6 +580,7 @@ void Player::doKeepAlive() {
                 }
                 else
                 {
+                    // Make sure time doesn't shift after leaving pause.
                     ros::WallDuration shift = ros::WallTime::now() - paused_time_;
                     paused_time_ = ros::WallTime::now();
          
@@ -433,6 +595,7 @@ void Player::doKeepAlive() {
                 {
                     printTime();
                     time_publisher_.runStalledClock(ros::WallDuration(.1));
+                    ros::spinOnce();
                 }
                 else
                     charsleftorpaused = false;
@@ -441,6 +604,7 @@ void Player::doKeepAlive() {
 
         printTime();
         time_publisher_.runClock(ros::WallDuration(.1));
+        ros::spinOnce();
     }
 }
 
diff --git a/tools/rosbag/src/recorder.cpp b/tools/rosbag/src/recorder.cpp
index c0c4602..a4e995c 100644
--- a/tools/rosbag/src/recorder.cpp
+++ b/tools/rosbag/src/recorder.cpp
@@ -60,7 +60,7 @@
 
 #include "ros/network.h"
 #include "ros/xmlrpc_manager.h"
-#include "XmlRpc.h"
+#include "xmlrpcpp/XmlRpc.h"
 
 #define foreach BOOST_FOREACH
 
@@ -348,6 +348,11 @@ void Recorder::updateFilenames() {
     if (options_.split)
         parts.push_back(boost::lexical_cast<string>(split_count_));
 
+    if (parts.size() == 0)
+    {
+      throw BagException("Bag filename is empty (neither of these was specified: prefix, append_date, split)");
+    }
+
     target_filename_ = parts[0];
     for (unsigned int i = 1; i < parts.size(); i++)
         target_filename_ += string("_") + parts[i];
diff --git a/tools/rosbag/src/rosbag/bag.py b/tools/rosbag/src/rosbag/bag.py
index f907b0a..1f9cf36 100644
--- a/tools/rosbag/src/rosbag/bag.py
+++ b/tools/rosbag/src/rosbag/bag.py
@@ -496,7 +496,8 @@ class Bag(object):
         else:
             if not self._connection_indexes:
                 raise ROSBagException('Bag contains no message')
-            start_stamp = min([index[0].time.to_sec() for index in self._connection_indexes.values()])
+            start_stamps = [index[0].time.to_sec() for index in self._connection_indexes.values() if index]
+            start_stamp = min(start_stamps) if start_stamps else 0
         
         return start_stamp
     
@@ -512,7 +513,8 @@ class Bag(object):
         else:
             if not self._connection_indexes:
                 raise ROSBagException('Bag contains no message')
-            end_stamp = max([index[-1].time.to_sec() for index in self._connection_indexes.values()])
+            end_stamps = [index[-1].time.to_sec() for index in self._connection_indexes.values() if index]
+            end_stamp = max(end_stamps) if end_stamps else 0
         
         return end_stamp
     
@@ -625,8 +627,10 @@ class Bag(object):
                     start_stamp = self._chunks[ 0].start_time.to_sec()
                     end_stamp   = self._chunks[-1].end_time.to_sec()
                 else:
-                    start_stamp = min([index[ 0].time.to_sec() for index in self._connection_indexes.values()])
-                    end_stamp   = max([index[-1].time.to_sec() for index in self._connection_indexes.values()])
+                    start_stamps = [index[0].time.to_sec() for index in self._connection_indexes.values() if index]
+                    start_stamp = min(start_stamps) if start_stamps else 0
+                    end_stamps = [index[-1].time.to_sec() for index in self._connection_indexes.values() if index]
+                    end_stamp = max(end_stamps) if end_stamps else 0
     
                 # Show duration
                 duration = end_stamp - start_stamp
@@ -808,8 +812,10 @@ class Bag(object):
                     start_stamp = self._chunks[ 0].start_time.to_sec()
                     end_stamp   = self._chunks[-1].end_time.to_sec()
                 else:
-                    start_stamp = min([index[ 0].time.to_sec() for index in self._connection_indexes.values()])
-                    end_stamp   = max([index[-1].time.to_sec() for index in self._connection_indexes.values()])
+                    start_stamps = [index[0].time.to_sec() for index in self._connection_indexes.values() if index]
+                    start_stamp = min(start_stamps) if start_stamps else 0
+                    end_stamps = [index[-1].time.to_sec() for index in self._connection_indexes.values() if index]
+                    end_stamp = max(end_stamps) if end_stamps else 0
                 
                 duration = end_stamp - start_stamp
                 s += 'duration: %.6f\n' % duration
diff --git a/tools/rosbag/src/rosbag/migration.py b/tools/rosbag/src/rosbag/migration.py
index 19ea6b1..94c94a4 100644
--- a/tools/rosbag/src/rosbag/migration.py
+++ b/tools/rosbag/src/rosbag/migration.py
@@ -968,7 +968,7 @@ class MessageMigrator(object):
                 found_stop = True
                 break
 
-        # Next see if we can create a valid rule
+        # Next see if we can create a valid rule, including the sub rules
         if not found_stop:
             for (ind, tmp_sn) in reversed(list(zip(range(len(sn_range)), sn_range))):
                 if (tmp_sn.new_class._type != new_class._type):
@@ -977,12 +977,13 @@ class MessageMigrator(object):
                 R = new_rule(self, 'GENERATED.' + new_rule.__name__)
                 if R.valid:
                     R.find_sub_paths()
-                    sn = ScaffoldNode(tmp_sn.new_class, new_class, R)
-                    self.extra_nodes.append(sn)
-                    sn_range = sn_range[:ind+1]
-                    sn_range.append(sn)
-                    found_stop = True
-                    break
+                    if R.sub_rules_valid:
+                        sn = ScaffoldNode(tmp_sn.new_class, new_class, R)
+                        self.extra_nodes.append(sn)
+                        sn_range = sn_range[:ind+1]
+                        sn_range.append(sn)
+                        found_stop = True
+                        break
 
         # If there were no valid implicit rules, we suggest a new one from to the end
         if not found_stop:
@@ -1006,7 +1007,19 @@ class MessageMigrator(object):
                 found_start = True
                 break
 
-        # Next see if we can create a valid rule
+        # Next see if we can create a valid rule directly to the end, including the sub rules
+        if not found_start:
+            new_rule = self.make_update_rule(old_class, new_class)
+            R = new_rule(self, 'GENERATED.' + new_rule.__name__)
+            if R.valid:
+                R.find_sub_paths()
+                if R.sub_rules_valid:
+                    sn = ScaffoldNode(old_class, new_class, R)
+                    self.extra_nodes.append(sn)
+                    self.found_paths[key] = [sn]
+                    return [sn]
+
+        # Next see if we can create a valid rule, including the sub rules
         if not found_start:
             for (ind, tmp_sn) in reversed(list(zip(range(len(sn_range)), sn_range))):
                 if (tmp_sn.old_class._type != old_class._type):
@@ -1015,12 +1028,13 @@ class MessageMigrator(object):
                 R = new_rule(self, 'GENERATED.' + new_rule.__name__)
                 if R.valid:
                     R.find_sub_paths()
-                    sn = ScaffoldNode(old_class, tmp_sn.old_class, R)
-                    self.extra_nodes.append(sn)
-                    sn_range = sn_range[ind:]
-                    sn_range.insert(0,sn)
-                    found_start = True
-                    break
+                    if R.sub_rules_valid:
+                        sn = ScaffoldNode(old_class, tmp_sn.old_class, R)
+                        self.extra_nodes.append(sn)
+                        sn_range = sn_range[ind:]
+                        sn_range.insert(0,sn)
+                        found_start = True
+                        break
 
         # If there were no valid implicit rules, we suggest a new one from the beginning
         if not found_start:
diff --git a/tools/rosbag/src/rosbag/rosbag_main.py b/tools/rosbag/src/rosbag/rosbag_main.py
index e434860..a9f36bc 100644
--- a/tools/rosbag/src/rosbag/rosbag_main.py
+++ b/tools/rosbag/src/rosbag/rosbag_main.py
@@ -65,6 +65,13 @@ def handle_split(option, opt_str, value, parser):
         print("Use of \"--split <MAX_SIZE>\" has been deprecated.  Please use --split --size <MAX_SIZE> or --split --duration <MAX_DURATION>", file=sys.stderr)
         parser.values.size = int(parser.rargs.pop(0))
 
+
+def _stop_process(signum, frame, old_handler, process):
+    process.terminate()
+    if old_handler:
+        old_handler(signum, frame)
+
+
 def record_cmd(argv):
     parser = optparse.OptionParser(usage="rosbag record TOPIC1 [TOPIC2 TOPIC3 ...]",
                                    description="Record a bag file with the contents of specified topics.",
@@ -124,9 +131,15 @@ def record_cmd(argv):
 
     cmd.extend(args)
 
+    old_handler = signal.signal(
+        signal.SIGTERM,
+        lambda signum, frame: _stop_process(signum, frame, old_handler, process)
+    )
     # Better way of handling it than os.execv
     # This makes sure stdin handles are passed to the process.
-    subprocess.call(cmd)
+    process = subprocess.Popen(cmd)
+    process.wait()
+
 
 def info_cmd(argv):
     parser = optparse.OptionParser(usage='rosbag info [options] BAGFILE1 [BAGFILE2 BAGFILE3 ...]',
@@ -208,6 +221,9 @@ def play_cmd(argv):
     parser.add_option("--topics", dest="topics", default=[],  callback=handle_topics, action="callback", help="topics to play back")
     parser.add_option("--pause-topics", dest="pause_topics", default=[],  callback=handle_pause_topics, action="callback", help="topics to pause on during playback")
     parser.add_option("--bags",  help="bags files to play back from")
+    parser.add_option("--wait-for-subscribers",  dest="wait_for_subscribers", default=False, action="store_true", help="wait for at least one subscriber on each topic before publishing")
+    parser.add_option("--rate-control-topic", dest="rate_control_topic", default='', type='str', help="watch the given topic, and if the last publish was more than <rate-control-max-delay> ago, wait until the topic publishes again to continue playback")
+    parser.add_option("--rate-control-max-delay", dest="rate_control_max_delay", default=1.0, type='float', help="maximum time difference from <rate-control-topic> before pausing")
 
     (options, args) = parser.parse_args(argv)
 
@@ -231,6 +247,7 @@ def play_cmd(argv):
     if options.loop:       cmd.extend(["--loop"])
     if options.keep_alive: cmd.extend(["--keep-alive"])
     if options.try_future: cmd.extend(["--try-future-version"])
+    if options.wait_for_subscribers: cmd.extend(["--wait-for-subscribers"])
 
     if options.clock:
         cmd.extend(["--clock", "--hz", str(options.freq)])
@@ -254,10 +271,23 @@ def play_cmd(argv):
     if options.topics or options.pause_topics:
         cmd.extend(['--bags'])
 
+    if options.rate_control_topic:
+        cmd.extend(['--rate-control-topic', str(options.rate_control_topic)])
+
+    if options.rate_control_max_delay:
+        cmd.extend(['--rate-control-max-delay', str(options.rate_control_max_delay)])
+
     cmd.extend(args)
+
+    old_handler = signal.signal(
+        signal.SIGTERM,
+        lambda signum, frame: _stop_process(signum, frame, old_handler, process)
+    )
     # Better way of handling it than os.execv
     # This makes sure stdin handles are passed to the process.
-    subprocess.call(cmd)
+    process = subprocess.Popen(cmd)
+    process.wait()
+
 
 def filter_cmd(argv):
     def expr_eval(expr):
@@ -455,7 +485,7 @@ def check_cmd(argv):
     migrations = checkbag(mm, args[0])
        
     if len(migrations) == 0:
-        print('Bag file is up to date.')
+        print('Bag file does not need any migrations.')
         exit(0)
         
     print('The following migrations need to occur:')
diff --git a/tools/rosbag/test/test_roundtrip.py b/tools/rosbag/test/test_roundtrip.py
new file mode 100644
index 0000000..ac35653
--- /dev/null
+++ b/tools/rosbag/test/test_roundtrip.py
@@ -0,0 +1,75 @@
+import unittest
+import tempfile
+import os
+
+import rosbag
+import rospy
+
+BAG_DIR = tempfile.mkdtemp(prefix='rosbag_tests')
+
+class TestRoundTrip(unittest.TestCase):
+    def _write_simple_bag(self, name):
+        from std_msgs.msg import Int32, String
+
+        with rosbag.Bag(name, 'w') as bag:
+            s = String(data='foo')
+            i = Int32(data=42)
+
+            bag.write('chatter', s)
+            bag.write('numbers', i)
+
+    def _fname(self, name):
+        return os.path.join(BAG_DIR, name)
+
+    def test_value_equality(self):
+        fname = self._fname('test_value_equality.bag')
+
+        self._write_simple_bag(fname)
+
+        with rosbag.Bag(fname) as bag:
+            numbers = list(bag.read_messages('numbers'))
+            chatter = list(bag.read_messages('chatter'))
+
+        self.assertEqual(len(numbers), 1)
+        self.assertEqual(len(chatter), 1)
+
+        numbers = numbers[0]
+        chatter = chatter[0]
+
+        # channel names
+        self.assertEqual(numbers[0], 'numbers')
+        self.assertEqual(chatter[0], 'chatter')
+
+        # values
+        self.assertEqual(numbers[1].data, 42)
+        self.assertEqual(chatter[1].data, 'foo')
+
+    @unittest.expectedFailure
+    def test_type_equality(self):
+        fname = self._fname('test_type_equality.bag')
+
+        from std_msgs.msg import Int32, String
+
+        self._write_simple_bag(fname)
+
+        with rosbag.Bag(fname) as bag:
+            numbers = next(bag.read_messages('numbers'))
+            chatter = next(bag.read_messages('chatter'))
+
+        self.assertEqual(numbers[1].__class__, Int32)
+        self.assertEqual(chatter[1].__class__, String)
+
+    @unittest.expectedFailure
+    def test_type_isinstance(self):
+        fname = self._fname('test_type_isinstance.bag')
+
+        from std_msgs.msg import Int32, String
+
+        self._write_simple_bag(fname)
+
+        with rosbag.Bag(fname) as bag:
+            numbers = next(bag.read_messages('numbers'))
+            chatter = next(bag.read_messages('chatter'))
+
+        self.assertIsInstance(numbers[1], Int32)
+        self.assertIsInstance(chatter[1], String)
diff --git a/tools/rosbag_storage/CHANGELOG.rst b/tools/rosbag_storage/CHANGELOG.rst
index 0b13730..8fc61fd 100644
--- a/tools/rosbag_storage/CHANGELOG.rst
+++ b/tools/rosbag_storage/CHANGELOG.rst
@@ -2,6 +2,19 @@
 Changelog for package rosbag_storage
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
+1.13.1 (2017-07-27)
+-------------------
+* fix buffer overflow vulnerability (`#1092 <https://github.com/ros/ros_comm/issues/1092>`_)
+* fix rosbag::View::iterator copy assignment operator (`#1017 <https://github.com/ros/ros_comm/issues/1017>`_)
+* fix open mode on Windows (`#1005 <https://github.com/ros/ros_comm/pull/1005>`_)
+* add swap function instead of copy constructor / assignment operator for rosbag::Bag (`#1000 <https://github.com/ros/ros_comm/issues/1000>`_)
+
+1.13.0 (2017-02-22)
+-------------------
+
+1.12.7 (2017-02-17)
+-------------------
+
 1.12.6 (2016-10-26)
 -------------------
 
diff --git a/tools/rosbag_storage/include/rosbag/bag.h b/tools/rosbag_storage/include/rosbag/bag.h
index e8a346e..14ad8a2 100644
--- a/tools/rosbag_storage/include/rosbag/bag.h
+++ b/tools/rosbag_storage/include/rosbag/bag.h
@@ -171,7 +171,12 @@ public:
     void write(std::string const& topic, ros::Time const& time, boost::shared_ptr<T> const& msg,
                boost::shared_ptr<ros::M_string> connection_header = boost::shared_ptr<ros::M_string>());
 
+    void swap(Bag&);
+
 private:
+    Bag(const Bag&);
+    Bag& operator=(const Bag&);
+
     // This helper function actually does the write with an arbitrary serializable message
     template<class T>
     void doWrite(std::string const& topic, ros::Time const& time, T const& msg, boost::shared_ptr<ros::M_string> const& connection_header);
@@ -621,6 +626,10 @@ void Bag::writeMessageDataRecord(uint32_t conn_id, ros::Time const& time, T cons
         curr_chunk_info_.start_time = time;
 }
 
+inline void swap(Bag& a, Bag& b) {
+    a.swap(b);
+}
+
 } // namespace rosbag
 
 #endif
diff --git a/tools/rosbag_storage/include/rosbag/buffer.h b/tools/rosbag_storage/include/rosbag/buffer.h
index 5f9cf1a..aef6c99 100644
--- a/tools/rosbag_storage/include/rosbag/buffer.h
+++ b/tools/rosbag_storage/include/rosbag/buffer.h
@@ -51,8 +51,11 @@ public:
     uint32_t getSize()     const;
 
     void setSize(uint32_t size);
+    void swap(Buffer& other);
 
 private:
+    Buffer(const Buffer&);
+    Buffer& operator=(const Buffer&);
     void ensureCapacity(uint32_t capacity);
 
 private:
@@ -61,6 +64,10 @@ private:
     uint32_t size_;
 };
 
+inline void swap(Buffer& a, Buffer& b) {
+    a.swap(b);
+}
+
 } // namespace rosbag
 
 #endif
diff --git a/tools/rosbag_storage/include/rosbag/chunked_file.h b/tools/rosbag_storage/include/rosbag/chunked_file.h
index c1c8cda..722aeca 100644
--- a/tools/rosbag_storage/include/rosbag/chunked_file.h
+++ b/tools/rosbag_storage/include/rosbag/chunked_file.h
@@ -79,8 +79,12 @@ public:
     bool        truncate(uint64_t length);
     void        seek(uint64_t offset, int origin = std::ios_base::beg); //!< seek to given offset from origin
     void        decompress(CompressionType compression, uint8_t* dest, unsigned int dest_len, uint8_t* source, unsigned int source_len);
+    void        swap(ChunkedFile& other);
 
 private:
+    ChunkedFile(const ChunkedFile&);
+    ChunkedFile& operator=(const ChunkedFile&);
+
     void open(std::string const& filename, std::string const& mode);
     void clearUnused();
 
@@ -98,6 +102,10 @@ private:
     boost::shared_ptr<Stream> write_stream_;
 };
 
+inline void swap(ChunkedFile& a, ChunkedFile& b) {
+    a.swap(b);
+}
+
 } // namespace rosbag
 
 #endif
diff --git a/tools/rosbag_storage/include/rosbag/stream.h b/tools/rosbag_storage/include/rosbag/stream.h
index 1f56381..2ef7fac 100644
--- a/tools/rosbag_storage/include/rosbag/stream.h
+++ b/tools/rosbag_storage/include/rosbag/stream.h
@@ -63,8 +63,11 @@ typedef compression::CompressionType CompressionType;
 
 class ChunkedFile;
 
+class FileAccessor;
+
 class ROSBAG_DECL Stream
 {
+    friend class FileAccessor;
 public:
     Stream(ChunkedFile* file);
     virtual ~Stream();
@@ -110,6 +113,13 @@ private:
     boost::shared_ptr<Stream> lz4_stream_;
 };
 
+class FileAccessor {
+    friend class ChunkedFile;
+    static void setFile(Stream& a, ChunkedFile* file) {
+        a.file_ = file;
+    }
+};
+
 class ROSBAG_DECL UncompressedStream : public Stream
 {
 public:
@@ -173,6 +183,8 @@ public:
     void decompress(uint8_t* dest, unsigned int dest_len, uint8_t* source, unsigned int source_len);
 
 private:
+    LZ4Stream(const LZ4Stream&);
+    LZ4Stream operator=(const LZ4Stream&);
     void writeStream(int action);
 
     char *buff_;
diff --git a/tools/rosbag_storage/include/rosbag/view.h b/tools/rosbag_storage/include/rosbag/view.h
index bce5676..ea9048a 100644
--- a/tools/rosbag_storage/include/rosbag/view.h
+++ b/tools/rosbag_storage/include/rosbag/view.h
@@ -63,6 +63,7 @@ public:
     {
     public:
         iterator(iterator const& i);
+        iterator &operator=(iterator const& i);
         iterator();
         ~iterator();
 
diff --git a/tools/rosbag_storage/package.xml b/tools/rosbag_storage/package.xml
index d88f581..f5ad42f 100644
--- a/tools/rosbag_storage/package.xml
+++ b/tools/rosbag_storage/package.xml
@@ -1,6 +1,6 @@
 <package>
   <name>rosbag_storage</name>
-  <version>1.12.6</version>
+  <version>1.13.1</version>
   <description>
     This is a set of tools for recording from and playing back ROS
     message without relying on the ROS client library.
diff --git a/tools/rosbag_storage/rosdoc.yaml b/tools/rosbag_storage/rosdoc.yaml
index 512d1f1..976fdf0 100644
--- a/tools/rosbag_storage/rosdoc.yaml
+++ b/tools/rosbag_storage/rosdoc.yaml
@@ -1,5 +1,3 @@
- - builder: epydoc
-   output_dir: python
  - builder: doxygen
    name: C++ API
    output_dir: c++
diff --git a/tools/rosbag_storage/src/bag.cpp b/tools/rosbag_storage/src/bag.cpp
index 62cd953..281f326 100644
--- a/tools/rosbag_storage/src/bag.cpp
+++ b/tools/rosbag_storage/src/bag.cpp
@@ -230,7 +230,7 @@ void Bag::readVersion() {
 #if defined(_MSC_VER)
     if (sscanf_s(version_line.c_str(), "#ROS%s V%d.%d", logtypename, sizeof(logtypename), &version_major, &version_minor) != 3)
 #else
-    if (sscanf(version_line.c_str(), "#ROS%s V%d.%d", logtypename, &version_major, &version_minor) != 3)
+    if (sscanf(version_line.c_str(), "#ROS%99s V%d.%d", logtypename, &version_major, &version_minor) != 3)
 #endif
         throw BagIOException("Error reading version line");
 
@@ -1117,4 +1117,35 @@ void Bag::write(char const* s, std::streamsize n) { file_.write((char*) s, n);
 void Bag::read(char* b, std::streamsize n) const  { file_.read(b, n);             }
 void Bag::seek(uint64_t pos, int origin) const    { file_.seek(pos, origin);      }
 
+void Bag::swap(Bag& other) {
+    using std::swap;
+    swap(mode_, other.mode_);
+    swap(file_, other.file_);
+    swap(version_, other.version_);
+    swap(compression_, other.compression_);
+    swap(chunk_threshold_, other.chunk_threshold_);
+    swap(bag_revision_, other.bag_revision_);
+    swap(file_size_, other.file_size_);
+    swap(file_header_pos_, other.file_header_pos_);
+    swap(index_data_pos_, other.index_data_pos_);
+    swap(connection_count_, other.connection_count_);
+    swap(chunk_count_, other.chunk_count_);
+    swap(chunk_open_, other.chunk_open_);
+    swap(curr_chunk_info_, other.curr_chunk_info_);
+    swap(curr_chunk_data_pos_, other.curr_chunk_data_pos_);
+    swap(topic_connection_ids_, other.topic_connection_ids_);
+    swap(header_connection_ids_, other.header_connection_ids_);
+    swap(connections_, other.connections_);
+    swap(chunks_, other.chunks_);
+    swap(connection_indexes_, other.connection_indexes_);
+    swap(curr_chunk_connection_indexes_, other.curr_chunk_connection_indexes_);
+    swap(header_buffer_, other.header_buffer_);
+    swap(record_buffer_, other.record_buffer_);
+    swap(chunk_buffer_, other.chunk_buffer_);
+    swap(decompress_buffer_, other.decompress_buffer_);
+    swap(outgoing_chunk_buffer_, other.outgoing_chunk_buffer_);
+    swap(current_buffer_, other.current_buffer_);
+    swap(decompressed_chunk_, other.decompressed_chunk_);
+}
+
 } // namespace rosbag
diff --git a/tools/rosbag_storage/src/buffer.cpp b/tools/rosbag_storage/src/buffer.cpp
index b3d217a..f51e624 100644
--- a/tools/rosbag_storage/src/buffer.cpp
+++ b/tools/rosbag_storage/src/buffer.cpp
@@ -34,6 +34,7 @@
 
 #include <stdlib.h>
 #include <assert.h>
+#include <utility>
 
 #include "rosbag/buffer.h"
 
@@ -71,4 +72,11 @@ void Buffer::ensureCapacity(uint32_t capacity) {
     assert(buffer_);
 }
 
+void Buffer::swap(Buffer& other) {
+    using std::swap;
+    swap(buffer_, other.buffer_);
+    swap(capacity_, other.capacity_);
+    swap(size_, other.size_);
+}
+
 } // namespace rosbag
diff --git a/tools/rosbag_storage/src/chunked_file.cpp b/tools/rosbag_storage/src/chunked_file.cpp
index 0e90b02..9eb6658 100644
--- a/tools/rosbag_storage/src/chunked_file.cpp
+++ b/tools/rosbag_storage/src/chunked_file.cpp
@@ -86,13 +86,14 @@ void ChunkedFile::open(string const& filename, string const& mode) {
 
     // Open the file
     if (mode == "r+b") {
-        // Read + write requires file to exists.  Create a new file if it doesn't exist.
+        // check if file already exists
         #if defined(_MSC_VER) && (_MSC_VER >= 1400 )
             fopen_s( &file_, filename.c_str(), "r" );
         #else
             file_ = fopen(filename.c_str(), "r");
         #endif
         if (file_ == NULL)
+            // create an empty file and open it for update
             #if defined(_MSC_VER) && (_MSC_VER >= 1400 )
                 fopen_s( &file_, filename.c_str(), "w+b" );
             #else
@@ -100,8 +101,9 @@ void ChunkedFile::open(string const& filename, string const& mode) {
             #endif
         else {
             fclose(file_);
+            // open existing file for update
             #if defined(_MSC_VER) && (_MSC_VER >= 1400 )
-                fopen_s( &file_, filename.c_str(), "w+b" );
+                fopen_s( &file_, filename.c_str(), "r+b" );
             #else
                 file_ = fopen(filename.c_str(), "r+b");
             #endif
@@ -221,4 +223,33 @@ void ChunkedFile::clearUnused() {
     nUnused_ = 0;
 }
 
+void ChunkedFile::swap(ChunkedFile& other) {
+    using std::swap;
+    using boost::swap;
+    swap(filename_, other.filename_);
+    swap(file_, other.file_);
+    swap(offset_, other.offset_);
+    swap(compressed_in_, other.compressed_in_);
+    swap(unused_, other.unused_);
+    swap(nUnused_, other.nUnused_);
+
+    swap(stream_factory_, other.stream_factory_);
+
+    FileAccessor::setFile(*stream_factory_->getStream(compression::Uncompressed), this);
+    FileAccessor::setFile(*stream_factory_->getStream(compression::BZ2), this);
+    FileAccessor::setFile(*stream_factory_->getStream(compression::LZ4), this);
+
+    FileAccessor::setFile(*other.stream_factory_->getStream(compression::Uncompressed), &other);
+    FileAccessor::setFile(*other.stream_factory_->getStream(compression::BZ2), &other);
+    FileAccessor::setFile(*other.stream_factory_->getStream(compression::LZ4), &other);
+
+    swap(read_stream_, other.read_stream_);
+    FileAccessor::setFile(*read_stream_, this);
+    FileAccessor::setFile(*other.read_stream_, &other);
+
+    swap(write_stream_, other.write_stream_);
+    FileAccessor::setFile(*write_stream_, this);
+    FileAccessor::setFile(*other.write_stream_, &other);
+}
+
 } // namespace rosbag
diff --git a/tools/rosbag_storage/src/view.cpp b/tools/rosbag_storage/src/view.cpp
index 7448c86..b388b4c 100644
--- a/tools/rosbag_storage/src/view.cpp
+++ b/tools/rosbag_storage/src/view.cpp
@@ -59,6 +59,19 @@ View::iterator::iterator(View* view, bool end) : view_(view), view_revision_(0),
 
 View::iterator::iterator(const iterator& i) : view_(i.view_), iters_(i.iters_), view_revision_(i.view_revision_), message_instance_(NULL) { }
 
+View::iterator &View::iterator::operator=(iterator const& i) {
+    if (this != &i) {
+        view_ = i.view_;
+        iters_ = i.iters_;
+        view_revision_ = i.view_revision_;
+        if (message_instance_ != NULL) {
+            delete message_instance_;
+            message_instance_ = NULL;
+        }
+    }
+    return *this;
+}
+
 void View::iterator::populate() {
     assert(view_ != NULL);
 
diff --git a/tools/rosconsole/CHANGELOG.rst b/tools/rosconsole/CHANGELOG.rst
index bcb9060..550f0a9 100644
--- a/tools/rosconsole/CHANGELOG.rst
+++ b/tools/rosconsole/CHANGELOG.rst
@@ -2,6 +2,17 @@
 Changelog for package rosconsole
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
+1.13.1 (2017-07-27)
+-------------------
+* remove extra semicolon in definition of macro ROSCONSOLE_PRINTF_ATTRIBUTE(a, b) (`#1056 <https://github.com/ros/ros_comm/pull/1056>`_)
+* add ROSCONSOLE_STDOUT_LINE_BUFFERED env var to force flushing stdout in Formatter::print (`#1012 <https://github.com/ros/ros_comm/issues/1012>`_)
+
+1.13.0 (2017-02-22)
+-------------------
+
+1.12.7 (2017-02-17)
+-------------------
+
 1.12.6 (2016-10-26)
 -------------------
 * add missing walltime to roscpp logging (`#879 <https://github.com/ros/ros_comm/pull/879>`_)
diff --git a/tools/rosconsole/include/ros/console.h b/tools/rosconsole/include/ros/console.h
index 28901d7..1b2f684 100644
--- a/tools/rosconsole/include/ros/console.h
+++ b/tools/rosconsole/include/ros/console.h
@@ -60,7 +60,7 @@
 
 #ifdef __GNUC__
 #if __GNUC__ >= 3
-#define ROSCONSOLE_PRINTF_ATTRIBUTE(a, b) __attribute__ ((__format__ (__printf__, a, b)));
+#define ROSCONSOLE_PRINTF_ATTRIBUTE(a, b) __attribute__ ((__format__ (__printf__, a, b)))
 #endif
 #endif
 
diff --git a/tools/rosconsole/package.xml b/tools/rosconsole/package.xml
index 8fc34d9..f8c99f1 100644
--- a/tools/rosconsole/package.xml
+++ b/tools/rosconsole/package.xml
@@ -1,6 +1,6 @@
 <package>
   <name>rosconsole</name>
-  <version>1.12.6</version>
+  <version>1.13.1</version>
   <description>ROS console output library.</description>
   <maintainer email="dthomas at osrfoundation.org">Dirk Thomas</maintainer>
   <license>BSD</license>
diff --git a/tools/rosconsole/src/rosconsole/rosconsole.cpp b/tools/rosconsole/src/rosconsole/rosconsole.cpp
index d07d90a..f419211 100644
--- a/tools/rosconsole/src/rosconsole/rosconsole.cpp
+++ b/tools/rosconsole/src/rosconsole/rosconsole.cpp
@@ -107,6 +107,9 @@ std::string g_last_error_message = "Unknown Error";
 #endif
 const char* g_format_string = "[${severity}] [${time}]: ${message}";
 
+bool g_force_stdout_line_buffered = false;
+bool g_stdout_flush_failure_reported = false;
+
 typedef std::map<std::string, std::string> M_string;
 M_string g_extra_fixed_tokens;
 
@@ -393,6 +396,16 @@ void Formatter::print(void* logger_handle, ::ros::console::Level level, const ch
   ss << COLOR_NORMAL;
 
   fprintf(f, "%s\n", ss.str().c_str());
+  
+  if (g_force_stdout_line_buffered && f == stdout)
+  {
+    int flush_result = fflush(f);
+    if (flush_result != 0 && !g_stdout_flush_failure_reported)
+    {
+      g_stdout_flush_failure_reported = true;
+      fprintf(stderr, "Error: failed to perform fflush on stdout, fflush return code is %d\n", flush_result);
+    }
+  }
 }
 
 Formatter g_formatter;
@@ -425,6 +438,20 @@ void initialize()
     backend::function_notifyLoggerLevelsChanged = notifyLoggerLevelsChanged;
     backend::function_print = _print;
 
+    std::string line_buffered;
+    if (get_environment_variable(line_buffered, "ROSCONSOLE_STDOUT_LINE_BUFFERED"))
+    {
+      if (line_buffered == "1")
+      {
+        g_force_stdout_line_buffered = true;
+      }
+      else if (line_buffered != "0")
+      {
+        fprintf(stderr, "Warning: unexpected value %s specified for ROSCONSOLE_STDOUT_LINE_BUFFERED. Default value 0 "
+          "will be used. Valid values are 1 or 0.\n", line_buffered.c_str());
+      }
+    }
+
     ::ros::console::impl::initialize();
     g_initialized = true;
   }
diff --git a/tools/rosgraph/CHANGELOG.rst b/tools/rosgraph/CHANGELOG.rst
index 88eae1a..3d6d930 100644
--- a/tools/rosgraph/CHANGELOG.rst
+++ b/tools/rosgraph/CHANGELOG.rst
@@ -2,6 +2,18 @@
 Changelog for package rosgraph
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
+1.13.1 (2017-07-27)
+-------------------
+* improve message when `roslogging` cannot change permissions (`#1068 <https://github.com/ros/ros_comm/issues/1068>`_)
+* allow python_logging.yaml for logging configuration (`#1061 <https://github.com/ros/ros_comm/issues/1061>`_)
+* write log for class method with class name (`#1043 <https://github.com/ros/ros_comm/issues/1043>`_)
+
+1.13.0 (2017-02-22)
+-------------------
+
+1.12.7 (2017-02-17)
+-------------------
+
 1.12.6 (2016-10-26)
 -------------------
 * change rospy default rosconsole format for consistency with roscpp (`#879 <https://github.com/ros/ros_comm/pull/879>`_)
diff --git a/tools/rosgraph/package.xml b/tools/rosgraph/package.xml
index 7de8943..608cd65 100644
--- a/tools/rosgraph/package.xml
+++ b/tools/rosgraph/package.xml
@@ -1,6 +1,6 @@
 <package>
   <name>rosgraph</name>
-  <version>1.12.6</version>
+  <version>1.13.1</version>
   <description>
     rosgraph contains the rosgraph command-line tool, which prints
     information about the ROS Computation Graph. It also provides an
@@ -16,6 +16,7 @@
 
   <run_depend>python-netifaces</run_depend>
   <run_depend>python-rospkg</run_depend>
+  <run_depend>python-yaml</run_depend>
 
   <test_depend>python-mock</test_depend>
 
diff --git a/tools/rosgraph/src/rosgraph/roslogging.py b/tools/rosgraph/src/rosgraph/roslogging.py
index e4cfafe..48e5024 100644
--- a/tools/rosgraph/src/rosgraph/roslogging.py
+++ b/tools/rosgraph/src/rosgraph/roslogging.py
@@ -39,12 +39,45 @@ import sys
 import time
 import logging
 import logging.config
+import inspect
+
+import yaml
 
 import rospkg
 from rospkg.environment import ROS_LOG_DIR
 
 class LoggingException(Exception): pass
 
+class RospyLogger(logging.getLoggerClass()):
+    def findCaller(self):
+        """
+        Find the stack frame of the caller so that we can note the source
+        file name, line number, and function name with class name if possible.
+        """
+        file_name, lineno, func_name = super(RospyLogger, self).findCaller()
+
+        f = inspect.currentframe()
+        if f is not None:
+            f = f.f_back
+        while hasattr(f, "f_code"):
+            # we search the right frame using the data already found by parent class
+            # following python logging findCaller() implementation logic
+            co = f.f_code
+            filename = os.path.normcase(co.co_filename)
+            if filename != file_name or f.f_lineno != lineno or co.co_name != func_name:
+                f = f.f_back
+                continue
+            # we found  the correct frame, now extending func_name with class name
+            try:
+                class_name = f.f_locals['self'].__class__.__name__
+                func_name = '%s.%s' % (class_name, func_name)
+            except KeyError:  # if the function is unbound, there is no self.
+                pass
+            break
+        return file_name, lineno, func_name
+
+logging.setLoggerClass(RospyLogger)
+
 def renew_latest_logdir(logfile_dir):
     log_dir = os.path.dirname(logfile_dir)
     latest_dir = os.path.join(log_dir, 'latest')
@@ -83,7 +116,13 @@ def configure_logging(logname, level=logging.INFO, filename=None, env=None):
             makedirs_with_parent_perms(logfile_dir)
         except OSError:
             # cannot print to screen because command-line tools with output use this
-            sys.stderr.write("WARNING: cannot create log directory [%s]. Please set %s to a writable location.\n"%(logfile_dir, ROS_LOG_DIR))
+            if os.path.exists(logfile_dir):
+                # We successfully created the logging folder, but could not change
+                # permissions of the new folder to the same as the parent folder
+                sys.stderr.write("WARNING: Could not change permissions for folder [%s], make sure that the parent folder has correct permissions.\n"%logfile_dir)
+            else:
+                # Could not create folder
+                sys.stderr.write("WARNING: cannot create log directory [%s]. Please set %s to a writable location.\n"%(logfile_dir, ROS_LOG_DIR))
             return None
     elif os.path.isfile(logfile_dir):
         raise LoggingException("Cannot save log files: file [%s] is in the way"%logfile_dir)
@@ -103,16 +142,17 @@ def configure_logging(logname, level=logging.INFO, filename=None, env=None):
     else:
         # search for logging config file in /etc/.  If it's not there,
         # look for it package-relative.
-        fname = 'python_logging.conf'
+        config_file = None
         rosgraph_d = rospkg.RosPack().get_path('rosgraph')
-        for f in [os.path.join(rospkg.get_ros_home(), 'config', fname),
-                  '/etc/ros/%s'%(fname),
-                  os.path.join(rosgraph_d, 'conf', fname)]:
-            if os.path.isfile(f):
-                config_file = f
+        for fname in ['python_logging.conf', 'python_logging.yaml']:
+            for f in [os.path.join(rospkg.get_ros_home(), 'config', fname),
+                      '/etc/ros/%s'%(fname),
+                      os.path.join(rosgraph_d, 'conf', fname)]:
+                if os.path.isfile(f):
+                    config_file = f
+                    break
+            if config_file is not None:
                 break
-        else:
-            config_file = None
 
     if config_file is None or not os.path.isfile(config_file):
         # logging is considered soft-fail
@@ -122,10 +162,18 @@ def configure_logging(logname, level=logging.INFO, filename=None, env=None):
     
     # pass in log_filename as argument to pylogging.conf
     os.environ['ROS_LOG_FILENAME'] = log_filename
-    # #3625: disabling_existing_loggers=False
-    logging.config.fileConfig(config_file, disable_existing_loggers=False)
+    if config_file.endswith(('.yaml', '.yml')):
+        with open(config_file) as f:
+            dict_conf = yaml.load(f)
+        dict_conf.setdefault('version', 1)
+        logging.config.dictConfig(dict_conf)
+    else:
+        # #3625: disabling_existing_loggers=False
+        logging.config.fileConfig(config_file, disable_existing_loggers=False)
+
     return log_filename
 
+
 def makedirs_with_parent_perms(p):
     """
     Create the directory using the permissions of the nearest
diff --git a/tools/rosgraph/test/test_roslogging.py b/tools/rosgraph/test/test_roslogging.py
new file mode 100644
index 0000000..3601d46
--- /dev/null
+++ b/tools/rosgraph/test/test_roslogging.py
@@ -0,0 +1,111 @@
+# Software License Agreement (BSD License)
+#
+# Copyright (c) 2016, Kentaro Wada.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+#  * Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+#  * Redistributions in binary form must reproduce the above
+#    copyright notice, this list of conditions and the following
+#    disclaimer in the documentation and/or other materials provided
+#    with the distribution.
+#  * Neither the name of Willow Garage, Inc. nor the names of its
+#    contributors may be used to endorse or promote products derived
+#    from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+
+import logging
+import os
+from StringIO import StringIO
+import sys
+
+from nose.tools import assert_regexp_matches
+import rosgraph.roslogging
+
+
+os.environ['ROSCONSOLE_FORMAT'] = ' '.join([
+    '${severity}',
+    '${message}',
+    '${walltime}',
+    '${thread}',
+    '${logger}',
+    '${file}',
+    '${line}',
+    '${function}',
+    '${node}',
+    '${time}',
+])
+rosgraph.roslogging.configure_logging('test_rosgraph', logging.INFO)
+loginfo = logging.getLogger('rosout').info
+
+# Remap stdout for testing
+f = StringIO()
+sys.stdout = f
+
+
+loginfo('on module')
+
+
+def logging_on_function():
+    loginfo('on function')
+
+logging_on_function()
+
+
+class LoggingOnClass(object):
+
+    def __init__(self):
+        loginfo('on method')
+
+LoggingOnClass()
+
+
+def test_rosconsole__logging_format():
+    this_file = os.path.abspath(__file__)
+    # this is necessary to avoid test fails because of .pyc cache file
+    base, ext = os.path.splitext(this_file)
+    if ext == '.pyc':
+        this_file = base + '.py'
+
+    for i, loc in enumerate(['module', 'function', 'method']):
+        if loc == 'module':
+            function = '<module>'
+        elif loc == 'function':
+            function = 'logging_on_function'
+        elif loc == 'method':
+            function = 'LoggingOnClass.__init__'
+        else:
+            raise ValueError
+
+        log_out = ' '.join([
+            'INFO',
+            'on ' + loc,
+            '[0-9]*\.[0-9]*',
+            '[0-9]*',
+            'rosout',
+            this_file,
+            '[0-9]*',
+            function,
+            '/unnamed',
+            '[0-9]*\.[0-9]*',
+        ])
+        assert_regexp_matches(f.getvalue().splitlines()[i], log_out)
+
+
+sys.stdout = sys.__stdout__
diff --git a/tools/rosgraph/test/test_roslogging_user_logger.py b/tools/rosgraph/test/test_roslogging_user_logger.py
new file mode 100644
index 0000000..8d20575
--- /dev/null
+++ b/tools/rosgraph/test/test_roslogging_user_logger.py
@@ -0,0 +1,118 @@
+# Software License Agreement (BSD License)
+#
+# Copyright (c) 2016, Kentaro Wada.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+#  * Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+#  * Redistributions in binary form must reproduce the above
+#    copyright notice, this list of conditions and the following
+#    disclaimer in the documentation and/or other materials provided
+#    with the distribution.
+#  * Neither the name of Willow Garage, Inc. nor the names of its
+#    contributors may be used to endorse or promote products derived
+#    from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+
+"""
+Test for rosgraph.roslogger with custom logger defined by user,
+to ensure the custom logger won't be overwritten by RospyLogger defined
+in rosgraph.roslogger.
+"""
+
+import logging
+import os
+from StringIO import StringIO
+import sys
+
+from nose.tools import assert_regexp_matches
+
+import rosgraph.roslogging
+
+
+# set user defined custom logger
+class UserCustomLogger(logging.Logger):
+    def findCaller(self):
+        """Returns static caller.
+
+        This method is being overwritten in rosgraph.roslogging.
+        """
+        return '<filename>', '<lineno>', '<func_name>'
+
+    def _log(self, level, msg, args, exc_info=None, extra=None):
+        """Write log with ROS_IP.
+
+        This method is not being overwritten in rosgraph.roslogging.
+        """
+        ros_ip = os.environ.get('ROS_IP', '<unknown ros_ip>')
+        msg = '%s %s' % (ros_ip, msg)
+        logging.Logger._log(self, level, msg, args, exc_info, extra)
+
+
+def setup_module():
+    logging.setLoggerClass(UserCustomLogger)
+
+
+def teardown_module():
+    logging.setLoggerClass(rosgraph.roslogging.RospyLogger)
+
+
+def test_roslogging_user_logger():
+    os.environ['ROS_IP'] = '127.0.0.1'
+    os.environ['ROSCONSOLE_FORMAT'] = ' '.join([
+        '${severity}',
+        '${message}',
+        '${walltime}',
+        '${thread}',
+        '${logger}',
+        '${file}',
+        '${line}',
+        '${function}',
+        '${node}',
+        '${time}',
+    ])
+    rosgraph.roslogging.configure_logging('test_rosgraph', logging.INFO)
+    loginfo = logging.getLogger('rosout.custom_logger_test').info
+
+    # Remap stdout for testing
+    f = StringIO()
+    sys.stdout = f
+
+    # Logging
+    msg = 'Hello world.'
+    loginfo(msg)
+
+    # Restore stdout
+    log_actual = f.getvalue().strip()
+    sys.stdout = sys.__stdout__
+
+    log_expected = ' '.join([
+        'INFO',
+        os.environ['ROS_IP'],
+        msg,
+        '[0-9]*\.[0-9]*',
+        '[0-9]*',
+        'rosout.custom_logger_test',
+        '<filename>',
+        '<lineno>',
+        '<func_name>',
+        '/unnamed',
+        '[0-9]*\.[0-9]*',
+    ])
+    assert_regexp_matches(log_actual, log_expected)
diff --git a/tools/roslaunch/CHANGELOG.rst b/tools/roslaunch/CHANGELOG.rst
index 5e2ff47..87a2b85 100644
--- a/tools/roslaunch/CHANGELOG.rst
+++ b/tools/roslaunch/CHANGELOG.rst
@@ -2,6 +2,24 @@
 Changelog for package roslaunch
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
+1.13.1 (2017-07-27)
+-------------------
+* add $(dirname) to get directory of current launch file (`#1103 <https://github.com/ros/ros_comm/pull/1103>`_)
+* clean the namespace to get rid of double or trailing forward slashes (`#1100 <https://github.com/ros/ros_comm/issues/1100>`_)
+* only launch core nodes if master was launched by roslaunch (`#1098 <https://github.com/ros/ros_comm/pull/1098>`_)
+* ensure pid file is removed on exit (`#1057 <https://github.com/ros/ros_comm/pull/1057>`_, `#1084 <https://github.com/ros/ros_comm/pull/1084>`_)
+* add yaml type for param tag (`#1045 <https://github.com/ros/ros_comm/issues/1045>`_)
+* ensure cwd exists (`#1031 <https://github.com/ros/ros_comm/pull/1031>`_)
+* respect if/unless for roslaunch-check (`#998 <https://github.com/ros/ros_comm/pull/998>`_)
+
+1.13.0 (2017-02-22)
+-------------------
+
+1.12.7 (2017-02-17)
+-------------------
+* improve error message for invalid tags (`#989 <https://github.com/ros/ros_comm/pull/989>`_)
+* fix caching logic to improve performance (`#931 <https://github.com/ros/ros_comm/pull/931>`_)
+
 1.12.6 (2016-10-26)
 -------------------
 * add USE_TEST_DEPENDENCIES option to roslaunch_add_file_check() (`#910 <https://github.com/ros/ros_comm/pull/910>`_)
diff --git a/tools/roslaunch/package.xml b/tools/roslaunch/package.xml
index dcafa2f..35a19e8 100644
--- a/tools/roslaunch/package.xml
+++ b/tools/roslaunch/package.xml
@@ -1,6 +1,6 @@
 <package>
   <name>roslaunch</name>
-  <version>1.12.6</version>
+  <version>1.13.1</version>
   <description>
     roslaunch is a tool for easily launching multiple ROS <a
     href="http://ros.org/wiki/Nodes">nodes</a> locally and remotely
diff --git a/tools/roslaunch/resources/example.launch b/tools/roslaunch/resources/example.launch
index 6b07bc5..0c389bf 100644
--- a/tools/roslaunch/resources/example.launch
+++ b/tools/roslaunch/resources/example.launch
@@ -59,4 +59,15 @@
   <!-- more compact import syntax -->
   <include ns="included2" file="$(find roslaunch)/resources/example-include.launch" />
   
+  <!-- Pass over an include and node with if-attributes that evaluate to false. -->
+  <arg name="false_arg" value="false" />
+  <include if="$(arg false_arg)" file="does/not/exist.launch" />
+  <node if="$(arg false_arg)" pkg="doesnt_exist" type="nope" name="nope" />
+
+  <!-- Pass over a group with an unless-attribute that evaluate to true. -->
+  <arg name="true_arg" value="true" />
+  <group unless="$(arg true_arg)">
+    <include file="does/not/exist.launch" />
+    <node pkg="doesnt_exist" type="nope" name="nope" />
+  </group>
 </launch>
diff --git a/tools/roslaunch/src/roslaunch/__init__.py b/tools/roslaunch/src/roslaunch/__init__.py
index 8d75fbc..6f04d30 100644
--- a/tools/roslaunch/src/roslaunch/__init__.py
+++ b/tools/roslaunch/src/roslaunch/__init__.py
@@ -296,21 +296,15 @@ def main(argv=sys.argv):
             # This is a roslaunch parent, spin up parent server and launch processes.
             # args are the roslaunch files to load
             from . import parent as roslaunch_parent
-            try:
-                # force a port binding spec if we are running a core
-                if options.core:
-                    options.port = options.port or DEFAULT_MASTER_PORT
-                p = roslaunch_parent.ROSLaunchParent(uuid, args, roslaunch_strs=roslaunch_strs,
-                        is_core=options.core, port=options.port, local_only=options.local_only,
-                        verbose=options.verbose, force_screen=options.force_screen,
-                        num_workers=options.num_workers, timeout=options.timeout)
-                p.start()
-                p.spin()
-            finally:
-                # remove the pid file
-                if options.pid_fn:
-                    try: os.unlink(options.pid_fn)
-                    except os.error: pass
+            # force a port binding spec if we are running a core
+            if options.core:
+                options.port = options.port or DEFAULT_MASTER_PORT
+            p = roslaunch_parent.ROSLaunchParent(uuid, args, roslaunch_strs=roslaunch_strs,
+                    is_core=options.core, port=options.port, local_only=options.local_only,
+                    verbose=options.verbose, force_screen=options.force_screen,
+                    num_workers=options.num_workers, timeout=options.timeout)
+            p.start()
+            p.spin()
 
     except RLException as e:
         roslaunch_core.printerrlog(str(e))
@@ -328,6 +322,12 @@ def main(argv=sys.argv):
     except Exception as e:
         traceback.print_exc()
         sys.exit(1)
+    finally:
+        # remove the pid file
+        if options is not None and options.pid_fn:
+            try: os.unlink(options.pid_fn)
+            except os.error: pass
+
 
 if __name__ == '__main__':
     main()
diff --git a/tools/roslaunch/src/roslaunch/core.py b/tools/roslaunch/src/roslaunch/core.py
index a6d43e3..86f9e97 100644
--- a/tools/roslaunch/src/roslaunch/core.py
+++ b/tools/roslaunch/src/roslaunch/core.py
@@ -39,6 +39,7 @@ Core roslaunch model and lower-level utility routines.
 import os
 import logging
 
+import re
 import socket
 import sys
 try:
@@ -456,6 +457,7 @@ class Node(object):
         self.type = node_type
         self.name = name or None
         self.namespace = rosgraph.names.make_global_ns(namespace or '/')
+        self.namespace = re.sub("//+", "/", self.namespace)
         self.machine_name = machine_name or None
         self.respawn = respawn
         self.respawn_delay = respawn_delay
diff --git a/tools/roslaunch/src/roslaunch/depends.py b/tools/roslaunch/src/roslaunch/depends.py
index 2cb8a75..79eb050 100644
--- a/tools/roslaunch/src/roslaunch/depends.py
+++ b/tools/roslaunch/src/roslaunch/depends.py
@@ -45,6 +45,7 @@ from xml.dom import Node as DomNode
 
 import rospkg
 
+from .loader import convert_value
 from .substitution_args import resolve_args
 
 NAME="roslaunch-deps"
@@ -94,20 +95,16 @@ def _get_arg_value(tag, context):
     else:
         raise RoslaunchDepsException("No value for arg [%s]"%(name))
 
-def _parse_arg(tag, context):
-    name = tag.attributes['name'].value
+def _check_ifunless(tag, context):
     if tag.attributes.has_key('if'):
         val = resolve_args(tag.attributes['if'].value, context)
-        if val == '1' or val == 'true':
-            return (name, _get_arg_value(tag, context))
+        if not convert_value(val, 'bool'):
+            return False
     elif tag.attributes.has_key('unless'):
         val = resolve_args(tag.attributes['unless'].value, context)
-        if val == '0' or val == 'false':
-            return (name, _get_arg_value(tag, context))
-    else:
-        return (name, _get_arg_value(tag, context))
-    # nothing to return (no value, or conditional wasn't satisfied)
-    return None
+        if convert_value(val, 'bool'):
+            return False
+    return True
 
 def _parse_subcontext(tags, context):
     subcontext = {'arg': {}}
@@ -116,12 +113,8 @@ def _parse_subcontext(tags, context):
        return subcontext
     
     for tag in [t for t in tags if t.nodeType == DomNode.ELEMENT_NODE]:
-        if tag.tagName == 'arg':
-            # None is returned for args with if/unless that evaluate to false
-            ret = _parse_arg(tag, context)
-            if ret is not None:
-                (name, val) = ret
-                subcontext['arg'][name] = val
+        if tag.tagName == 'arg' and _check_ifunless(tag, context):
+            subcontext['arg'][tag.attributes['name'].value] = _get_arg_value(tag, context)
     return subcontext
 
 def _parse_launch(tags, launch_file, file_deps, verbose, context):
@@ -130,6 +123,8 @@ def _parse_launch(tags, launch_file, file_deps, verbose, context):
             
     # process group, include, node, and test tags from launch file
     for tag in [t for t in tags if t.nodeType == DomNode.ELEMENT_NODE]:
+        if not _check_ifunless(tag, context):
+            continue
 
         if tag.tagName == 'group':
             
@@ -137,10 +132,8 @@ def _parse_launch(tags, launch_file, file_deps, verbose, context):
             _parse_launch(tag.childNodes, launch_file, file_deps, verbose, context)
 
         elif tag.tagName == 'arg':
-            v = _parse_arg(tag, context)
-            if v:
-                (name, val) = v
-                context['arg'][name] = val
+            context['arg'][tag.attributes['name'].value] = _get_arg_value(tag, context)
+
         elif tag.tagName == 'include':
             try:
                 sub_launch_file = resolve_args(tag.attributes['file'].value, context)
diff --git a/tools/roslaunch/src/roslaunch/launch.py b/tools/roslaunch/src/roslaunch/launch.py
index 758d6fe..8b5e424 100644
--- a/tools/roslaunch/src/roslaunch/launch.py
+++ b/tools/roslaunch/src/roslaunch/launch.py
@@ -382,6 +382,9 @@ class ROSLaunchRunner(object):
     def _launch_master(self):
         """
         Launches master if requested. 
+        @return: True if a master was launched, False if a master was
+        already running.
+        @rtype: bool
         @raise RLException: if master launch fails
         """
         m = self.config.master
@@ -426,6 +429,8 @@ class ROSLaunchRunner(object):
             self.logger.info("setting /roslaunch/uris/%s__%s' to %s"%(hostname, port, self.server_uri))
             param_server.setParam(_ID, '/roslaunch/uris/%s__%s'%(hostname, port),self.server_uri)
 
+        return not is_running
+
     def _check_and_set_run_id(self, param_server, run_id):
         """
         Initialize self.run_id to existing value or setup parameter
@@ -627,8 +632,9 @@ class ROSLaunchRunner(object):
             self.remote_runner.add_process_listener(self.listeners)            
 
         # start up the core: master + core nodes defined in core.xml
-        self._launch_master()
-        self._launch_core_nodes()        
+        launched = self._launch_master()
+        if launched:
+            self._launch_core_nodes()
         
         # run exectuables marked as setup period. this will block
         # until these executables exit. setup executable have to run
diff --git a/tools/roslaunch/src/roslaunch/loader.py b/tools/roslaunch/src/roslaunch/loader.py
index dac9ac4..8b884b6 100644
--- a/tools/roslaunch/src/roslaunch/loader.py
+++ b/tools/roslaunch/src/roslaunch/loader.py
@@ -39,12 +39,13 @@ General routines and representations for loading roslaunch model.
 import os
 from copy import deepcopy
 
+import yaml
+
 from roslaunch.core import Param, RosbinExecutable, RLException, PHASE_SETUP
 
 from rosgraph.names import make_global_ns, ns_join, PRIV_NAME, load_mappings, is_legal_name, canonicalize_name
 
 #lazy-import global for yaml and rosparam
-yaml = None
 rosparam = None
 
 class LoadException(RLException):
@@ -88,12 +89,17 @@ def convert_value(value, type_):
     elif type_ == 'double':
         return float(value)
     elif type_ == 'bool' or type_ == 'boolean':
-        value = value.lower()
+        value = value.lower().strip()
         if value == 'true' or value == '1':
             return True
         elif value == 'false' or value == '0':
             return False
         raise ValueError("%s is not a '%s' type"%(value, type_))
+    elif type_ == 'yaml':
+        try:
+            return yaml.load(value)
+        except yaml.parser.ParserError as e:
+            raise ValueError(e)
     else:
         raise ValueError("Unknown type '%s'"%type_)        
 
@@ -395,10 +401,6 @@ class Loader(object):
                     text = f.read()
                     
             # parse YAML text
-            # - lazy import
-            global yaml
-            if yaml is None:
-                import yaml
             # - lazy import: we have to import rosparam in oder to to configure the YAML constructors
             global rosparam
             if rosparam is None:
@@ -468,7 +470,7 @@ class Loader(object):
             return convert_value(value.strip(), ptype)
         elif textfile is not None:
             with open(textfile, 'r') as f:
-                return f.read()
+                return convert_value(f.read(), ptype)
         elif binfile is not None:
             try:
                 from xmlrpc.client import Binary
@@ -498,7 +500,7 @@ class Loader(object):
                 raise
             if c_value is None:
                 raise ValueError("parameter: unable to get output of command [%s]"%command)
-            return c_value
+            return convert_value(c_value, ptype)
         else: #_param_tag prevalidates, so this should not be reachable
             raise ValueError("unable to determine parameter value")
 
diff --git a/tools/roslaunch/src/roslaunch/nodeprocess.py b/tools/roslaunch/src/roslaunch/nodeprocess.py
index 8df5ce5..cc86a4a 100644
--- a/tools/roslaunch/src/roslaunch/nodeprocess.py
+++ b/tools/roslaunch/src/roslaunch/nodeprocess.py
@@ -290,6 +290,12 @@ class LocalProcess(Process):
                 cwd = get_ros_root()
             else:
                 cwd = rospkg.get_ros_home()
+            if not os.path.exists(cwd):
+                try:
+                    os.makedirs(cwd)
+                except OSError:
+                    # exist_ok=True
+                    pass
 
             _logger.info("process[%s]: start w/ args [%s]", self.name, self.args)
             _logger.info("process[%s]: cwd will be [%s]", self.name, cwd)
diff --git a/tools/roslaunch/src/roslaunch/substitution_args.py b/tools/roslaunch/src/roslaunch/substitution_args.py
index 6e06bef..806ab3f 100644
--- a/tools/roslaunch/src/roslaunch/substitution_args.py
+++ b/tools/roslaunch/src/roslaunch/substitution_args.py
@@ -119,6 +119,21 @@ def _anon(resolved, a, args, context):
     anon_context = context['anon']
     return resolved.replace("$(%s)" % a, _eval_anon(id=args[0], anons=anon_context))
 
+def _eval_dirname(filename):
+    if not filename:
+        raise SubstitutionException("Cannot substitute $(dirname), no file/directory information available.")
+    return os.path.abspath(os.path.dirname(filename))
+
+def _dirname(resolved, a, args, context):
+    """
+    process $(dirname)
+    @return: updated resolved argument
+    @rtype: str
+    @raise SubstitutionException: if no information about the current launch file is available, for example
+           if XML was passed via stdin, or this is a remote launch.
+    """
+    return resolved.replace("$(%s)" % a, _eval_dirname(context.get('filename', None)))
+
 def _eval_find(pkg):
     rp = _get_rospack()
     return rp.get_path(pkg)
@@ -144,21 +159,25 @@ def _find(resolved, a, args, context):
     rp = _get_rospack()
     if path:
         source_path_to_packages = rp.get_custom_cache('source_path_to_packages', {})
+        res = None
         try:
-            return _find_executable(
-                resolve_without_path, a, [args[0], path], context,
-                source_path_to_packages=source_path_to_packages)
-        except SubstitutionException:
-            pass
-        try:
-            return _find_resource(
+            res = _find_executable(
                 resolve_without_path, a, [args[0], path], context,
                 source_path_to_packages=source_path_to_packages)
         except SubstitutionException:
             pass
+        if res is None:
+            try:
+                res = _find_resource(
+                    resolve_without_path, a, [args[0], path], context,
+                    source_path_to_packages=source_path_to_packages)
+            except SubstitutionException:
+                pass
         # persist mapping of packages in rospack instance
         if source_path_to_packages:
             rp.set_custom_cache('source_path_to_packages', source_path_to_packages)
+        if res is not None:
+            return res
     pkg_path = rp.get_path(args[0])
     if path:
         pkg_path = os.path.join(pkg_path, path)
@@ -312,7 +331,13 @@ def _eval(s, context):
     def _eval_anon_context(id): return _eval_anon(id, anons=context['anon'])
     # inject arg context
     def _eval_arg_context(name): return convert_value(_eval_arg(name, args=context['arg']), 'auto')
-    functions = dict(anon=_eval_anon_context, arg=_eval_arg_context)
+    # inject dirname context
+    def _eval_dirname_context(): return _eval_dirname(context['filename'])
+    functions = {
+        'anon': _eval_anon_context,
+        'arg': _eval_arg_context,
+        'dirname': _eval_dirname_context
+    }
     functions.update(_eval_dict)
 
     # ignore values containing double underscores (for safety)
@@ -321,7 +346,7 @@ def _eval(s, context):
         raise SubstitutionException("$(eval ...) may not contain double underscore expressions")
     return str(eval(s, {}, _DictWrapper(context['arg'], functions)))
 
-def resolve_args(arg_str, context=None, resolve_anon=True):
+def resolve_args(arg_str, context=None, resolve_anon=True, filename=None):
     """
     Resolves substitution args (see wiki spec U{http://ros.org/wiki/roslaunch}).
 
@@ -355,6 +380,7 @@ def resolve_args(arg_str, context=None, resolve_anon=True):
     commands = {
         'env': _env,
         'optenv': _optenv,
+        'dirname': _dirname,
         'anon': _anon,
         'arg': _arg,
     }
@@ -367,7 +393,7 @@ def resolve_args(arg_str, context=None, resolve_anon=True):
     return resolved
 
 def _resolve_args(arg_str, context, resolve_anon, commands):
-    valid = ['find', 'env', 'optenv', 'anon', 'arg']
+    valid = ['find', 'env', 'optenv', 'dirname', 'anon', 'arg']
     resolved = arg_str
     for a in _collect_args(arg_str):
         splits = [s for s in a.split(' ') if s]
diff --git a/tools/roslaunch/src/roslaunch/xmlloader.py b/tools/roslaunch/src/roslaunch/xmlloader.py
index ff07ff4..9136f09 100644
--- a/tools/roslaunch/src/roslaunch/xmlloader.py
+++ b/tools/roslaunch/src/roslaunch/xmlloader.py
@@ -180,6 +180,8 @@ class XmlLoader(loader.Loader):
         """
         # resolve_args gets called a lot, so we optimize by testing for dollar sign before resolving
         if args and '$' in args:
+            # Populate resolve_dict with name of the current file being processed.
+            context.resolve_dict['filename'] = context.filename
             return substitution_args.resolve_args(args, context=context.resolve_dict, resolve_anon=self.resolve_anon)
         else:
             return args
@@ -409,7 +411,7 @@ class XmlLoader(loader.Loader):
                 elif tag_name == 'env':
                     self._env_tag(t, env_context, ros_config)
                 else:
-                    ros_config.add_config_error("WARN: unrecognized '%s' tag in <node> tag. Node xml is %s"%(t.tagName, tag.toxml()))
+                    ros_config.add_config_error("WARN: unrecognized '%s' child tag in the parent tag element: %s"%(t.tagName, tag.toxml()))
 
             # #1036 evaluate all ~params in context
             # TODO: can we get rid of force_local (above), remove this for loop, and just rely on param_tag logic instead?
diff --git a/tools/roslaunch/test/unit/test_substitution_args.py b/tools/roslaunch/test/unit/test_substitution_args.py
index 630896c..0456f29 100644
--- a/tools/roslaunch/test/unit/test_substitution_args.py
+++ b/tools/roslaunch/test/unit/test_substitution_args.py
@@ -96,7 +96,7 @@ def test_resolve_args():
 
     anon_context = {'foo': 'bar'}
     arg_context = {'fuga': 'hoge', 'car': 'cdr', 'arg': 'foo', 'True': 'False'}
-    context = {'anon': anon_context, 'arg': arg_context }
+    context = {'anon': anon_context, 'arg': arg_context, 'filename': '/path/to/file.launch'}
         
     tests = [
         ('$(find roslaunch)', roslaunch_dir),
@@ -119,6 +119,7 @@ def test_resolve_args():
         ('$(optenv NOT_ROS_ROOT)more stuff', 'more stuff'),
         ('$(optenv NOT_ROS_ROOT alternate)', 'alternate'),
         ('$(optenv NOT_ROS_ROOT alternate text)', 'alternate text'),
+        ('$(dirname)/foo', '/path/to/foo'),
 
         # #1776
         ('$(anon foo)', 'bar'),
@@ -177,6 +178,8 @@ def test_resolve_args():
         '$(optenv)',
         '$(anon)',
         '$(anon foo bar)',            
+        # Should fail without the supplied context.
+        '$(dirname)'
         ]
     for f in failures:
         try:
diff --git a/tools/roslaunch/test/unit/test_xmlloader.py b/tools/roslaunch/test/unit/test_xmlloader.py
index a796de4..3986815 100644
--- a/tools/roslaunch/test/unit/test_xmlloader.py
+++ b/tools/roslaunch/test/unit/test_xmlloader.py
@@ -1064,3 +1064,18 @@ class TestXmlLoader(unittest.TestCase):
         #    self.fail('should have thrown an exception')
         #except roslaunch.xmlloader.XmlParseException:
         #    pass
+
+    # Test for $(dirname) behaviour across included files.
+    def test_dirname(self):
+        loader = roslaunch.xmlloader.XmlLoader()
+        filename = os.path.join(self.xml_dir, 'test-dirname.xml')
+
+        mock = RosLaunchMock()
+        loader.load(filename, mock)
+
+        param_d = {}
+        for p in mock.params:
+            param_d[p.key] = p.value
+
+        self.assertEquals(param_d['/foo'], self.xml_dir + '/bar')
+        self.assertEquals(param_d['/bar'], self.xml_dir + '/test-dirname/baz')
diff --git a/tools/roslaunch/test/xml/test-dirname.xml b/tools/roslaunch/test/xml/test-dirname.xml
new file mode 100644
index 0000000..d78c8fe
--- /dev/null
+++ b/tools/roslaunch/test/xml/test-dirname.xml
@@ -0,0 +1,4 @@
+<launch>
+  <param name="foo" value="$(dirname)/bar" />
+  <include file="$(dirname)/test-dirname/included.xml" />
+</launch>
diff --git a/tools/roslaunch/test/xml/test-dirname/included.xml b/tools/roslaunch/test/xml/test-dirname/included.xml
new file mode 100644
index 0000000..38e0865
--- /dev/null
+++ b/tools/roslaunch/test/xml/test-dirname/included.xml
@@ -0,0 +1,3 @@
+<launch>
+  <param name="bar" value="$(dirname)/baz" />
+</launch>
diff --git a/tools/roslaunch/test/xml/test-params-valid.xml b/tools/roslaunch/test/xml/test-params-valid.xml
index 428a9b4..7ae940c 100644
--- a/tools/roslaunch/test/xml/test-params-valid.xml
+++ b/tools/roslaunch/test/xml/test-params-valid.xml
@@ -17,6 +17,9 @@
   
   <param name="somefloat1" value="3.14159" type="double" />  
   <param name="somefloat2" value="5.0" />
+
+  <param name="someyaml1" value="[0, 1, 2]" type="yaml" />
+  <param name="someyaml2" value="{string1: bar2, string2: '10', integer1: 1, float1: 3.14, list1: [0, 1, 2], list2: ['a', 'b', 'c']}" type="yaml" />
   
   <!-- you can set parameters in child namespaces -->
   <param name="wg/wgchildparam" value="a child namespace parameter 1" />  
@@ -32,6 +35,12 @@
   <!-- upload the output of a command as a param. -->
   <param name="commandoutput" command="cat "$(find roslaunch)/resources/example.launch"" />
 
+  <!-- upload the output of a command as a param as types. -->
+  <param name="commandoutputinteger" type="int" command="echo 0" />
+  <param name="commandoutputdouble" type="double" command="echo 10" />
+  <param name="commandoutputbool" type="bool" command="echo true" />
+  <param name="commandoutputyaml" type="yaml" command="cat "$(find roslaunch)/test/params.yaml"" />
+
 
   <!-- test that we can override params -->
   <param name="override" value="fail" />
diff --git a/tools/rosmaster/CHANGELOG.rst b/tools/rosmaster/CHANGELOG.rst
index 2e0e405..66cce47 100644
--- a/tools/rosmaster/CHANGELOG.rst
+++ b/tools/rosmaster/CHANGELOG.rst
@@ -2,6 +2,17 @@
 Changelog for package rosmaster
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
+1.13.1 (2017-07-27)
+-------------------
+* close CLOSE_WAIT sockets by default (`#1104 <https://github.com/ros/ros_comm/issues/1104>`_)
+
+1.13.0 (2017-02-22)
+-------------------
+
+1.12.7 (2017-02-17)
+-------------------
+* add more logging to publisher update calls (`#979 <https://github.com/ros/ros_comm/issues/979>`_)
+
 1.12.6 (2016-10-26)
 -------------------
 
diff --git a/tools/rosmaster/package.xml b/tools/rosmaster/package.xml
index ded9c60..b22d0ef 100644
--- a/tools/rosmaster/package.xml
+++ b/tools/rosmaster/package.xml
@@ -1,6 +1,6 @@
 <package>
   <name>rosmaster</name>
-  <version>1.12.6</version>
+  <version>1.13.1</version>
   <description>
     ROS <a href="http://ros.org/wiki/Master">Master</a> implementation.
   </description>
diff --git a/tools/rosmaster/src/rosmaster/master_api.py b/tools/rosmaster/src/rosmaster/master_api.py
index 8d0afd3..fc99369 100644
--- a/tools/rosmaster/src/rosmaster/master_api.py
+++ b/tools/rosmaster/src/rosmaster/master_api.py
@@ -202,10 +202,20 @@ def publisher_update_task(api, topic, pub_uris):
     @param pub_uris: list of publisher APIs to send to node
     @type  pub_uris: [str]
     """
-    
-    mloginfo("publisherUpdate[%s] -> %s", topic, api)
-    #TODO: check return value for errors so we can unsubscribe if stale
-    xmlrpcapi(api).publisherUpdate('/master', topic, pub_uris)
+    msg = "publisherUpdate[%s] -> %s %s" % (topic, api, pub_uris)
+    mloginfo(msg)
+    start_sec = time.time()
+    try:
+        #TODO: check return value for errors so we can unsubscribe if stale
+        ret = xmlrpcapi(api).publisherUpdate('/master', topic, pub_uris)
+        msg_suffix = "result=%s" % ret
+    except Exception as ex:
+        msg_suffix = "exception=%s" % ex
+        raise
+    finally:
+        delta_sec = time.time() - start_sec
+        mloginfo("%s: sec=%0.2f, %s", msg, delta_sec, msg_suffix)
+
 
 def service_update_task(api, service, uri):
     """
diff --git a/tools/rosmaster/src/rosmaster/util.py b/tools/rosmaster/src/rosmaster/util.py
index 5b9e3d1..ee7d609 100644
--- a/tools/rosmaster/src/rosmaster/util.py
+++ b/tools/rosmaster/src/rosmaster/util.py
@@ -49,6 +49,8 @@ from defusedxml.xmlrpc import monkey_patch
 monkey_patch()
 del monkey_patch
 
+import socket
+
 _proxies = {} #cache ServerProxys
 def xmlrpcapi(uri):
     """
@@ -62,9 +64,19 @@ def xmlrpcapi(uri):
         return None
     if not uri in _proxies:
         _proxies[uri] = ServerProxy(uri)
+    close_half_closed_sockets()
     return _proxies[uri]
 
 
+def close_half_closed_sockets():
+    for proxy in _proxies.values():
+        transport = proxy("transport")
+        if transport._connection and transport._connection[1] is not None and transport._connection[1].sock is not None:
+            state = transport._connection[1].sock.getsockopt(socket.SOL_TCP, socket.TCP_INFO)
+            if state == 8:  # CLOSE_WAIT
+                transport.close()
+
+
 def remove_server_proxy(uri):
     if uri in _proxies:
         del _proxies[uri]
diff --git a/tools/rosmsg/CHANGELOG.rst b/tools/rosmsg/CHANGELOG.rst
index 9a6eeca..2c1f68f 100644
--- a/tools/rosmsg/CHANGELOG.rst
+++ b/tools/rosmsg/CHANGELOG.rst
@@ -2,6 +2,17 @@
 Changelog for package rosmsg
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
+1.13.1 (2017-07-27)
+-------------------
+* fix rosmsg show from bag (`#1006 <https://github.com/ros/ros_comm/pull/1006>`_)
+
+1.13.0 (2017-02-22)
+-------------------
+
+1.12.7 (2017-02-17)
+-------------------
+* add rosmsg info as alias of rosmsg show (`#941 <https://github.com/ros/ros_comm/issues/941>`_)
+
 1.12.6 (2016-10-26)
 -------------------
 
diff --git a/tools/rosmsg/package.xml b/tools/rosmsg/package.xml
index f2acb02..04cdff6 100644
--- a/tools/rosmsg/package.xml
+++ b/tools/rosmsg/package.xml
@@ -1,6 +1,6 @@
 <package>
   <name>rosmsg</name>
-  <version>1.12.6</version>
+  <version>1.13.1</version>
   <description>
     rosmsg contains two command-line tools: <tt>rosmsg</tt> and
     <tt>rossrv</tt>. <tt>rosmsg</tt> is a command-line tool for
@@ -21,6 +21,7 @@
 
   <run_depend version_gte="0.6.4">catkin</run_depend>
   <run_depend>genmsg</run_depend>
+  <run_depend version_gte="0.6.5">genpy</run_depend>
   <run_depend>python-rospkg</run_depend>
   <run_depend>rosbag</run_depend>
   <run_depend>roslib</run_depend>
diff --git a/tools/rosmsg/src/rosmsg/__init__.py b/tools/rosmsg/src/rosmsg/__init__.py
index 2d17424..eff4b94 100644
--- a/tools/rosmsg/src/rosmsg/__init__.py
+++ b/tools/rosmsg/src/rosmsg/__init__.py
@@ -48,6 +48,7 @@ from catkin.find_in_workspaces import find_in_workspaces
 
 import rospkg
 import genmsg
+from genpy.dynamic import generate_dynamic
 
 import roslib.message
 import rosbag
@@ -578,9 +579,9 @@ def _stdin_arg(parser, full):
             parser.error("you may only specify one %s"%full)
         return options, args[0]
     
-def rosmsg_cmd_show(mode, full):
+def rosmsg_cmd_show(mode, full, alias='show'):
     cmd = "ros%s"%(mode[1:])
-    parser = OptionParser(usage="usage: %s show [options] <%s>"%(cmd, full))
+    parser = OptionParser(usage="usage: %s %s [options] <%s>"%(cmd, alias, full))
     parser.add_option("-r", "--raw",
                       dest="raw", default=False,action="store_true",
                       help="show raw message text, including comments")
@@ -603,7 +604,14 @@ def rosmsg_cmd_show(mode, full):
         for topic, msg, t in rosbag.Bag(bag_file).read_messages(raw=True):
             datatype, _, _, _, pytype = msg
             if datatype == arg:
-                print(get_msg_text(datatype, options.raw, pytype._full_text))
+                if options.raw:
+                    print(pytype._full_text)
+                else:
+                    context = genmsg.MsgContext.create_default()
+                    msgs = generate_dynamic(datatype, pytype._full_text)
+                    for t, msg in msgs.items():
+                        context.register(t, msg._spec)
+                    print(spec_to_str(context, msgs[datatype]._spec))
                 break
     else:
         rospack = rospkg.RosPack()
@@ -713,6 +721,7 @@ def fullusage(mode):
 
 Commands:
 \t%(cmd)s show\tShow %(type_lower)s description
+\t%(cmd)s info\tAlias for %(cmd)s show
 \t%(cmd)s list\tList all %(type_lower)ss
 \t%(cmd)s md5\tDisplay %(type_lower)s md5sum
 \t%(cmd)s package\tList %(type_lower)ss in a package
@@ -741,8 +750,8 @@ def rosmsgmain(mode=MODE_MSG):
             sys.exit(0)
 
         command = sys.argv[1]
-        if command == 'show':
-            sys.exit(rosmsg_cmd_show(ext, full))
+        if command in ('show', 'info'):
+            sys.exit(rosmsg_cmd_show(ext, full, command))
         elif command == 'package':
             rosmsg_cmd_package(ext, full)
         elif command == 'packages':
diff --git a/tools/rosnode/CHANGELOG.rst b/tools/rosnode/CHANGELOG.rst
index c2b403b..2a1c454 100644
--- a/tools/rosnode/CHANGELOG.rst
+++ b/tools/rosnode/CHANGELOG.rst
@@ -2,6 +2,15 @@
 Changelog for package rosnode
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
+1.13.1 (2017-07-27)
+-------------------
+
+1.13.0 (2017-02-22)
+-------------------
+
+1.12.7 (2017-02-17)
+-------------------
+
 1.12.6 (2016-10-26)
 -------------------
 
diff --git a/tools/rosnode/package.xml b/tools/rosnode/package.xml
index f1e4063..9df6633 100644
--- a/tools/rosnode/package.xml
+++ b/tools/rosnode/package.xml
@@ -1,6 +1,6 @@
 <package>
   <name>rosnode</name>
-  <version>1.12.6</version>
+  <version>1.13.1</version>
   <description>
     rosnode is a command-line tool for displaying debug information
     about ROS <a href="http://www.ros.org/wiki/Nodes">Nodes</a>,
diff --git a/tools/rosout/CHANGELOG.rst b/tools/rosout/CHANGELOG.rst
index 99af09f..6ed15f7 100644
--- a/tools/rosout/CHANGELOG.rst
+++ b/tools/rosout/CHANGELOG.rst
@@ -2,6 +2,18 @@
 Changelog for package rosout
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
+1.13.1 (2017-07-27)
+-------------------
+* move code from init to initializer (`#990 <https://github.com/ros/ros_comm/issues/990>`_)
+
+1.13.0 (2017-02-22)
+-------------------
+* modify rosout log rotation to actually "rotate" old files (`#854 <https://github.com/ros/ros_comm/issues/854>`_)
+* add node name to the output in rosout.log (`#912 <https://github.com/ros/ros_comm/issues/912>`_)
+
+1.12.7 (2017-02-17)
+-------------------
+
 1.12.6 (2016-10-26)
 -------------------
 
diff --git a/tools/rosout/package.xml b/tools/rosout/package.xml
index 84c8b1c..c567732 100644
--- a/tools/rosout/package.xml
+++ b/tools/rosout/package.xml
@@ -1,6 +1,6 @@
 <package>
   <name>rosout</name>
-  <version>1.12.6</version>
+  <version>1.13.1</version>
   <description>
      System-wide logging mechanism for messages sent to the /rosout topic.
   </description>
diff --git a/tools/rosout/rosout.cpp b/tools/rosout/rosout.cpp
index 95fb328..b367ae3 100644
--- a/tools/rosout/rosout.cpp
+++ b/tools/rosout/rosout.cpp
@@ -67,19 +67,19 @@ public:
   ros::Subscriber rosout_sub_;
   ros::Publisher agg_pub_;
 
-  Rosout()
+  Rosout() :
+    log_file_name_(ros::file_log::getLogDirectory() + "/rosout.log"),
+    handle_(NULL),
+    max_file_size_(100*1024*1024),
+    current_file_size_(0),
+    max_backup_index_(10),
+    current_backup_index_(0)
   {
     init();
   }
 
   void init()
   {
-    max_file_size_ = 100*1024*1024;
-    current_file_size_ = 0;
-    max_backup_index_ = 10;
-    current_backup_index_ = 0;
-
-    log_file_name_ = ros::file_log::getLogDirectory() + "/rosout.log";
     handle_ = fopen(log_file_name_.c_str(), "w");
 
     if (handle_ == 0)
@@ -141,7 +141,8 @@ public:
       ss << msg->level << " ";
     }
 
-    ss << "[" << msg->file << ":" << msg->line << "(" << msg->function << ") ";
+    ss << msg->name << " ";
+    ss << "[" << msg->file << ":" << msg->line << "(" << msg->function << ")] ";
 
     ss << "[topics: ";
     std::vector<std::string>::const_iterator it = msg->topics.begin();
@@ -177,40 +178,42 @@ public:
       // check for rolling
       if (current_file_size_ > max_file_size_)
       {
+        std::cout << "rosout log file " << log_file_name_.c_str() << " reached max size, rotating log files" << std::endl;
         if (fclose(handle_))
         {
           std::cerr << "Error closing rosout log file '" << log_file_name_.c_str() << "': " << strerror(ferror(handle_)) << std::endl;
         }
-        current_backup_index_++;
-        if (current_backup_index_ <= max_backup_index_)
+        if (current_backup_index_ == max_backup_index_)
         {
           std::stringstream backup_file_name;
-          backup_file_name << log_file_name_ << "." << current_backup_index_;
-          int rc = rename(log_file_name_.c_str(), backup_file_name.str().c_str());
+          backup_file_name << log_file_name_ << "." << max_backup_index_;
+          int rc = remove(backup_file_name.str().c_str());
           if (rc != 0)
           {
-            rc = remove(backup_file_name.str().c_str());
-            if (rc == 0)
-            {
-              rc = rename(log_file_name_.c_str(), backup_file_name.str().c_str());
-              if (rc)
-              {
-                std::cerr << "Error rotating rosout log file '" << log_file_name_.c_str() << "' to '" << backup_file_name.str().c_str() << "': " << strerror(errno);
-              }
-            }
-          }
-          if (rc)
-          {
-            std::cerr << "Error rotating rosout log file '" << log_file_name_.c_str() << "'' to '" << backup_file_name.str().c_str() << "'" << std::endl;
+            std::cerr << "Error deleting oldest rosout log file '" << backup_file_name.str().c_str() << "': " << strerror(errno) << std::endl;
           }
-          else
+        }
+        std::size_t i = std::min(max_backup_index_, current_backup_index_ + 1);
+        while (i > 0)
+        {
+          std::stringstream current_file_name;
+          current_file_name << log_file_name_;
+          if (i > 1)
           {
-            std::cout << "rosout log file " << log_file_name_.c_str() << " reached max size, back up data to " << backup_file_name.str().c_str() << std::endl;
+            current_file_name << "." << (i - 1);
           }
-          if (current_backup_index_ == max_backup_index_)
+          std::stringstream rotated_file_name;
+          rotated_file_name << log_file_name_ << "." << i;
+          int rc = rename(current_file_name.str().c_str(), rotated_file_name.str().c_str());
+          if (rc != 0)
           {
-            current_backup_index_ = 0;
+            std::cerr << "Error rotating rosout log file '" << current_file_name.str().c_str() << "' to '" << rotated_file_name.str().c_str() << "': " << strerror(errno) << std::endl;
           }
+          --i;
+        }
+        if (current_backup_index_ < max_backup_index_)
+        {
+          ++current_backup_index_;
         }
         handle_ = fopen(log_file_name_.c_str(), "w");
         if (handle_ == 0)
diff --git a/tools/rosparam/CHANGELOG.rst b/tools/rosparam/CHANGELOG.rst
index 89892f0..863adde 100644
--- a/tools/rosparam/CHANGELOG.rst
+++ b/tools/rosparam/CHANGELOG.rst
@@ -2,6 +2,15 @@
 Changelog for package rosparam
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
+1.13.1 (2017-07-27)
+-------------------
+
+1.13.0 (2017-02-22)
+-------------------
+
+1.12.7 (2017-02-17)
+-------------------
+
 1.12.6 (2016-10-26)
 -------------------
 
diff --git a/tools/rosparam/package.xml b/tools/rosparam/package.xml
index 394e80f..43d01ee 100644
--- a/tools/rosparam/package.xml
+++ b/tools/rosparam/package.xml
@@ -1,6 +1,6 @@
 <package>
   <name>rosparam</name>
-  <version>1.12.6</version>
+  <version>1.13.1</version>
   <description>
     rosparam contains the rosparam command-line tool for getting and
     setting ROS Parameters on the <a
diff --git a/tools/rosservice/CHANGELOG.rst b/tools/rosservice/CHANGELOG.rst
index 00ea319..ed89737 100644
--- a/tools/rosservice/CHANGELOG.rst
+++ b/tools/rosservice/CHANGELOG.rst
@@ -2,6 +2,15 @@
 Changelog for package rosservice
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
+1.13.1 (2017-07-27)
+-------------------
+
+1.13.0 (2017-02-22)
+-------------------
+
+1.12.7 (2017-02-17)
+-------------------
+
 1.12.6 (2016-10-26)
 -------------------
 
diff --git a/tools/rosservice/package.xml b/tools/rosservice/package.xml
index a0a3b67..4bb48f8 100644
--- a/tools/rosservice/package.xml
+++ b/tools/rosservice/package.xml
@@ -1,6 +1,6 @@
 <package>
   <name>rosservice</name>
-  <version>1.12.6</version>
+  <version>1.13.1</version>
   <description>
     rosservice contains the rosservice command-line tool for listing
     and querying ROS <a
diff --git a/tools/rostest/CHANGELOG.rst b/tools/rostest/CHANGELOG.rst
index f491436..546fbfa 100644
--- a/tools/rostest/CHANGELOG.rst
+++ b/tools/rostest/CHANGELOG.rst
@@ -2,6 +2,16 @@
 Changelog for package rostest
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
+1.13.1 (2017-07-27)
+-------------------
+* check clock publication neatly in publishtest (`#973 <https://github.com/ros/ros_comm/issues/973>`_)
+
+1.13.0 (2017-02-22)
+-------------------
+
+1.12.7 (2017-02-17)
+-------------------
+
 1.12.6 (2016-10-26)
 -------------------
 
diff --git a/tools/rostest/nodes/hztest b/tools/rostest/nodes/hztest
index d8e5f9d..f8c3c28 100755
--- a/tools/rostest/nodes/hztest
+++ b/tools/rostest/nodes/hztest
@@ -120,7 +120,7 @@ Test Duration: %s"""%(hz, hzerror, topic, test_duration))
         self.assert_(hz >= 0.0, "bad parameter (hz)")
         self.assert_(hzerror >= 0.0, "bad parameter (hzerror)")
         self.assert_(test_duration > 0.0, "bad parameter (test_duration)")
-        self.assert_(len(topic), "bad parameter (topic")
+        self.assert_(len(topic), "bad parameter (topic)")
 
         if hz == 0:
             self.min_rate = 0.0
diff --git a/tools/rostest/nodes/publishtest b/tools/rostest/nodes/publishtest
index b298491..92bd0e7 100755
--- a/tools/rostest/nodes/publishtest
+++ b/tools/rostest/nodes/publishtest
@@ -54,6 +54,7 @@ Author: Kentaro Wada <www.kentaro.wada at gmail.com>
 """
 
 import sys
+import time
 import unittest
 
 from nose.tools import assert_true
@@ -107,10 +108,15 @@ class PublishTest(unittest.TestCase):
     def test_publish(self):
         """Test topics are published and messages come"""
         use_sim_time = rospy.get_param('/use_sim_time', False)
-        while use_sim_time and (rospy.Time.now() == rospy.Time(0)):
-            rospy.logwarn('/use_sim_time is specified and rostime is 0, '
-                          '/clock is published?')
-            rospy.sleep(0.1)
+        t_start = time.time()
+        while not rospy.is_shutdown() and \
+                use_sim_time and (rospy.Time.now() == rospy.Time(0)):
+            rospy.logwarn_throttle(
+                1, '/use_sim_time is specified and rostime is 0, /clock is published?')
+            if time.time() - t_start > 10:
+                self.fail('Timed out (10s) of /clock publication.')
+            # must use time.sleep because /clock isn't yet published, so rospy.sleep hangs.
+            time.sleep(0.1)
         # subscribe topics
         checkers = []
         for topic in self.topics:
diff --git a/tools/rostest/package.xml b/tools/rostest/package.xml
index 947f681..388f31f 100644
--- a/tools/rostest/package.xml
+++ b/tools/rostest/package.xml
@@ -1,6 +1,6 @@
 <package>
   <name>rostest</name>
-  <version>1.12.6</version>
+  <version>1.13.1</version>
   <description>
      Integration test suite based on roslaunch that is compatible with xUnit frameworks.
   </description>
diff --git a/tools/rostopic/CHANGELOG.rst b/tools/rostopic/CHANGELOG.rst
index f851856..b59ae17 100644
--- a/tools/rostopic/CHANGELOG.rst
+++ b/tools/rostopic/CHANGELOG.rst
@@ -2,6 +2,16 @@
 Changelog for package rostopic
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
+1.13.1 (2017-07-27)
+-------------------
+* fix rostopic prining long integers (`#1110 <https://github.com/ros/ros_comm/pull/1110>`_)
+
+1.13.0 (2017-02-22)
+-------------------
+
+1.12.7 (2017-02-17)
+-------------------
+
 1.12.6 (2016-10-26)
 -------------------
 * fix typo of arg for _str_plot function (`#915 <https://github.com/ros/ros_comm/issues/915>`_)
diff --git a/tools/rostopic/package.xml b/tools/rostopic/package.xml
index 212b1b1..b6a1c26 100644
--- a/tools/rostopic/package.xml
+++ b/tools/rostopic/package.xml
@@ -1,6 +1,6 @@
 <package>
   <name>rostopic</name>
-  <version>1.12.6</version>
+  <version>1.13.1</version>
   <description>
     rostopic contains the rostopic command-line tool for displaying
     debug information about
diff --git a/tools/rostopic/src/rostopic/__init__.py b/tools/rostopic/src/rostopic/__init__.py
index f33bf0a..c32e33e 100644
--- a/tools/rostopic/src/rostopic/__init__.py
+++ b/tools/rostopic/src/rostopic/__init__.py
@@ -64,6 +64,12 @@ import rosgraph
 #TODO: lazy-import rospy or move rospy-dependent routines to separate location
 import rospy
 
+try:
+    long
+except NameError:
+    long = int
+
+
 class ROSTopicException(Exception):
     """
     Base exception class of rostopic-related errors
@@ -687,7 +693,7 @@ def _sub_str_plot_fields(val, f, field_filter):
     """recursive helper function for _str_plot_fields"""
     # CSV
     type_ = type(val)
-    if type_ in (bool, int, float) or \
+    if type_ in (bool, int, long, float) or \
            isinstance(val, genpy.TVal):
         return f
     # duck-type check for messages
@@ -708,7 +714,7 @@ def _sub_str_plot_fields(val, f, field_filter):
         val0 = val[0]
         type0 = type(val0)
         # no arrays of arrays
-        if type0 in (bool, int, float) or \
+        if type0 in (bool, int, long, float) or \
                isinstance(val0, genpy.TVal):
             return ','.join(["%s%s"%(f,x) for x in range(0,len(val))])
         elif _isstring_type(type0):
@@ -757,7 +763,7 @@ def _sub_str_plot(val, time_offset, field_filter):
     
     if type_ == bool:
         return '1' if val else '0'
-    elif type_ in (int, float) or \
+    elif type_ in (int, long, float) or \
            isinstance(val, genpy.TVal):
         if time_offset is not None and isinstance(val, genpy.Time):
             return str(val-time_offset)
@@ -783,7 +789,7 @@ def _sub_str_plot(val, time_offset, field_filter):
         type0 = type(val0)
         if type0 == bool:
             return ','.join([('1' if v else '0') for v in val])
-        elif type0 in (int, float) or \
+        elif type0 in (int, long, float) or \
                isinstance(val0, genpy.TVal):
             return ','.join([str(v) for v in val])
         elif _isstring_type(type0):
diff --git a/tools/topic_tools/CHANGELOG.rst b/tools/topic_tools/CHANGELOG.rst
index 7e87fb1..b3a1a24 100644
--- a/tools/topic_tools/CHANGELOG.rst
+++ b/tools/topic_tools/CHANGELOG.rst
@@ -2,6 +2,15 @@
 Changelog for package topic_tools
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
+1.13.1 (2017-07-27)
+-------------------
+
+1.13.0 (2017-02-22)
+-------------------
+
+1.12.7 (2017-02-17)
+-------------------
+
 1.12.6 (2016-10-26)
 -------------------
 
diff --git a/tools/topic_tools/package.xml b/tools/topic_tools/package.xml
index 341e3fc..5bdc67b 100644
--- a/tools/topic_tools/package.xml
+++ b/tools/topic_tools/package.xml
@@ -1,6 +1,6 @@
 <package>
   <name>topic_tools</name>
-  <version>1.12.6</version>
+  <version>1.13.1</version>
   <description>
     Tools for directing, throttling, selecting, and otherwise messing with
     ROS topics at a meta level. None of the programs in this package actually
diff --git a/utilities/message_filters/CHANGELOG.rst b/utilities/message_filters/CHANGELOG.rst
index ba69af8..804daf6 100644
--- a/utilities/message_filters/CHANGELOG.rst
+++ b/utilities/message_filters/CHANGELOG.rst
@@ -2,6 +2,15 @@
 Changelog for package message_filters
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
+1.13.1 (2017-07-27)
+-------------------
+
+1.13.0 (2017-02-22)
+-------------------
+
+1.12.7 (2017-02-17)
+-------------------
+
 1.12.6 (2016-10-26)
 -------------------
 * use boost::bind to bind the callback function (`#906 <https://github.com/ros/ros_comm/pull/906>`_)
diff --git a/utilities/message_filters/package.xml b/utilities/message_filters/package.xml
index f5d88ff..67d368a 100644
--- a/utilities/message_filters/package.xml
+++ b/utilities/message_filters/package.xml
@@ -1,6 +1,6 @@
 <package>
   <name>message_filters</name>
-  <version>1.12.6</version>
+  <version>1.13.1</version>
   <description>
     A set of message filters which take in messages and may output those messages at a later time, based on the conditions that filter needs met.
   </description>
diff --git a/utilities/roslz4/CHANGELOG.rst b/utilities/roslz4/CHANGELOG.rst
index 5b38e47..39c0f67 100644
--- a/utilities/roslz4/CHANGELOG.rst
+++ b/utilities/roslz4/CHANGELOG.rst
@@ -2,6 +2,16 @@
 Changelog for package roslz4
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
+1.13.1 (2017-07-27)
+-------------------
+* add XXH_NAMESPACE, for namespace emulation in C (`#1065 <https://github.com/ros/ros_comm/pull/1065>`_)
+
+1.13.0 (2017-02-22)
+-------------------
+
+1.12.7 (2017-02-17)
+-------------------
+
 1.12.6 (2016-10-26)
 -------------------
 
diff --git a/utilities/roslz4/CMakeLists.txt b/utilities/roslz4/CMakeLists.txt
index 68f65f7..ae9d75f 100644
--- a/utilities/roslz4/CMakeLists.txt
+++ b/utilities/roslz4/CMakeLists.txt
@@ -31,6 +31,9 @@ add_library(roslz4 src/lz4s.c src/xxhash.c)
 set_source_files_properties(
   src/lz4s.c
 PROPERTIES COMPILE_FLAGS "-Wno-sign-compare")
+set_source_files_properties(
+  src/lz4s.c src/xxhash.c
+PROPERTIES COMPILE_DEFINITIONS "XXH_NAMESPACE=ROSLZ4_")
 target_link_libraries(roslz4 ${lz4_LIBRARIES} ${catkin_LIBRARIES})
 
 if(NOT ANDROID)
diff --git a/utilities/roslz4/package.xml b/utilities/roslz4/package.xml
index 29bb773..dcc1e09 100644
--- a/utilities/roslz4/package.xml
+++ b/utilities/roslz4/package.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0"?>
 <package>
   <name>roslz4</name>
-  <version>1.12.6</version>
+  <version>1.13.1</version>
   <description>
     A Python and C++ implementation of the LZ4 streaming format.  Large data
     streams are split into blocks which are compressed using the very fast LZ4
diff --git a/utilities/roslz4/src/xxhash.h b/utilities/roslz4/src/xxhash.h
index a319bcc..3560bf2 100644
--- a/utilities/roslz4/src/xxhash.h
+++ b/utilities/roslz4/src/xxhash.h
@@ -69,6 +69,28 @@ extern "C" {
 //****************************
 typedef enum { XXH_OK=0, XXH_ERROR } XXH_errorcode;
 
+/*!XXH_NAMESPACE, aka Namespace Emulation :
+
+If you want to include _and expose_ xxHash functions from within your own library,
+but also want to avoid symbol collisions with other libraries which may also include xxHash,
+
+you can use XXH_NAMESPACE, to automatically prefix any public symbol from xxhash library
+with the value of XXH_NAMESPACE (therefore, avoid NULL and numeric values).
+
+Note that no change is required within the calling program as long as it includes `xxhash.h` :
+regular symbol name will be automatically translated by this header.
+*/
+#ifdef XXH_NAMESPACE
+#  define XXH_CAT(A,B) A##B
+#  define XXH_NAME2(A,B) XXH_CAT(A,B)
+#  define XXH32 XXH_NAME2(XXH_NAMESPACE, XXH32)
+#  define XXH32_sizeofState XXH_NAME2(XXH_NAMESPACE, XXH32_sizeofState)
+#  define XXH32_resetState XXH_NAME2(XXH_NAMESPACE, XXH32_resetState)
+#  define XXH32_init XXH_NAME2(XXH_NAMESPACE, XXH32_init)
+#  define XXH32_update XXH_NAME2(XXH_NAMESPACE, XXH32_update)
+#  define XXH32_intermediateDigest XXH_NAME2(XXH_NAMESPACE, XXH32_intermediateDigest)
+#  define XXH32_digest XXH_NAME2(XXH_NAMESPACE, XXH32_digest)
+#endif
 
 
 //****************************
diff --git a/utilities/roswtf/CHANGELOG.rst b/utilities/roswtf/CHANGELOG.rst
index ebadb28..3ced5ec 100644
--- a/utilities/roswtf/CHANGELOG.rst
+++ b/utilities/roswtf/CHANGELOG.rst
@@ -2,6 +2,16 @@
 Changelog for package roswtf
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
+1.13.1 (2017-07-27)
+-------------------
+* improve roswtf tests (`#1101 <https://github.com/ros/ros_comm/pull/1101>`_, `#1102 <https://github.com/ros/ros_comm/pull/1102>`_)
+
+1.13.0 (2017-02-22)
+-------------------
+
+1.12.7 (2017-02-17)
+-------------------
+
 1.12.6 (2016-10-26)
 -------------------
 
diff --git a/utilities/roswtf/package.xml b/utilities/roswtf/package.xml
index 140f792..24a53cf 100644
--- a/utilities/roswtf/package.xml
+++ b/utilities/roswtf/package.xml
@@ -1,6 +1,6 @@
 <package>
   <name>roswtf</name>
-  <version>1.12.6</version>
+  <version>1.13.1</version>
   <description>
      roswtf is a tool for diagnosing issues with a running ROS system. Think of it as a FAQ implemented in code.
   </description>
@@ -24,6 +24,8 @@
   <run_depend>rosservice</run_depend>
 
   <test_depend>cmake_modules</test_depend>  <!-- since the other packages recursively depend on it roswtf needs to find it during its own tests -->
+  <test_depend>rosbag</test_depend>
+  <test_depend>std_srvs</test_depend>
 
   <export>
     <rosdoc config="rosdoc.yaml"/>
diff --git a/utilities/roswtf/src/roswtf/environment.py b/utilities/roswtf/src/roswtf/environment.py
index b112609..1e21065 100644
--- a/utilities/roswtf/src/roswtf/environment.py
+++ b/utilities/roswtf/src/roswtf/environment.py
@@ -128,7 +128,7 @@ def ros_test_results_dir_check(ctx):
 def pythonpath_check(ctx):
     # used to have a lot more checks here, but trying to phase out need for roslib on custom PYTHONPATH
     path = ctx.pythonpath
-    roslib_count = len(set([p for p in paths(path) if 'roslib' in p]))
+    roslib_count = len(set([p for p in paths(path) if 'roslib' in p.split(os.sep)]))
     if roslib_count > 1:
         return "Multiple roslib directories in PYTHONPATH (there should only be one)"
 
diff --git a/utilities/roswtf/src/roswtf/rosdep_db.py b/utilities/roswtf/src/roswtf/rosdep_db.py
index 3173a91..285dab8 100644
--- a/utilities/roswtf/src/roswtf/rosdep_db.py
+++ b/utilities/roswtf/src/roswtf/rosdep_db.py
@@ -41,15 +41,16 @@ def get_user_home_directory():
     return os.path.expanduser("~")
 
 
-def rosdep_database_initialized_check(ctx):
-    """Makes sure rosdep database is initialized"""
+def rosdep_database_updated_check(ctx):
+    """Makes sure rosdep database is updated"""
     if not os.path.exists((os.path.join(get_user_home_directory(), '.ros', 'rosdep', 'sources.cache', 'index'))):
-        return "Please initialize rosdep database with sudo rosdep init."
+        return "Please update rosdep database with 'rosdep update'."
+
 
 warnings = []
 
-errors = [(rosdep_database_initialized_check,
-           "ROS Dep database not initialized: "),
+errors = [(rosdep_database_updated_check,
+           "ROS Dep database not updated: "),
          ]
 
 
diff --git a/utilities/roswtf/test/check_roswtf_command_line_online.py b/utilities/roswtf/test/check_roswtf_command_line_online.py
index 46676c0..7a0cfa5 100755
--- a/utilities/roswtf/test/check_roswtf_command_line_online.py
+++ b/utilities/roswtf/test/check_roswtf_command_line_online.py
@@ -80,11 +80,15 @@ class TestRostopicOnline(unittest.TestCase):
         pkgs = ['roswtf',
             'rosgraph', 'roslaunch', 'roslib', 'rosnode', 'rosservice',
             'rosbag', 'rosbag_storage', 'roslz4', 'rosconsole', 'roscpp', 'rosgraph_msgs', 'roslang', 'rosmaster', 'rosmsg', 'rosout', 'rosparam', 'rospy', 'rostest', 'rostopic', 'topic_tools', 'xmlrpcpp',
+            'std_srvs',  # ros_comm_msgs
             'cpp_common', 'roscpp_serialization', 'roscpp_traits', 'rostime',  # roscpp_core
             'rosbuild', 'rosclean', 'rosunit',  # ros
             'rospack', 'std_msgs', 'message_runtime', 'message_generation', 'gencpp', 'genlisp', 'genpy', 'genmsg', 'catkin',
         ]
-        paths = [rospack.get_path(pkg) for pkg in pkgs]
+        try:
+            paths = [rospack.get_path(pkg) for pkg in pkgs]
+        except rospkg.ResourceNotFound as e:
+            assert False, 'rospkg.ResourceNotFound: ' + str(e)
         try:
             path = rospack.get_path('cmake_modules')
         except rospkg.ResourceNotFound:
@@ -127,13 +131,15 @@ class TestRostopicOnline(unittest.TestCase):
             'No errors or warnings' in output or 'Found 1 error' in output,
             'CMD[%s] OUTPUT[%s]%s' %
             (' '.join(cmd), output, '\nstderr[%s]' % error if error else ''))
-        if 'No errors or warnings' in output:
-            self.assert_('ERROR' not in output, 'OUTPUT[%s]' % output)
+        allowed_errors = 0
         if 'Found 1 error' in output:
             self.assert_(output.count('ERROR') == 1, 'OUTPUT[%s]' % output)
             self.assert_(
-                'Error: the rosdep view is empty' not in output,
+                'ROS Dep database not updated' in output,
                 'OUTPUT[%s]' % output)
+            allowed_errors += 1
+        if 'No errors or warnings' in output:
+            self.assert_(output.count('ERROR') <= allowed_errors, 'OUTPUT[%s]' % output)
 
 if __name__ == '__main__':
     rostest.run(PKG, NAME, TestRostopicOnline, sys.argv)
diff --git a/utilities/roswtf/test/test_roswtf_command_line_offline.py b/utilities/roswtf/test/test_roswtf_command_line_offline.py
index 81ea381..ea2c879 100644
--- a/utilities/roswtf/test/test_roswtf_command_line_offline.py
+++ b/utilities/roswtf/test/test_roswtf_command_line_offline.py
@@ -69,6 +69,7 @@ class TestRoswtfOffline(unittest.TestCase):
         pkgs = ['roswtf',
             'rosgraph', 'roslaunch', 'roslib', 'rosnode', 'rosservice',
             'rosbag', 'rosbag_storage', 'roslz4', 'rosconsole', 'roscpp', 'rosgraph_msgs', 'roslang', 'rosmaster', 'rosmsg', 'rosout', 'rosparam', 'rospy', 'rostest', 'rostopic', 'topic_tools', 'xmlrpcpp',
+            'std_srvs',  # ros_comm_msgs
             'cpp_common', 'roscpp_serialization', 'roscpp_traits', 'rostime',  # roscpp_core
             'rosbuild', 'rosclean', 'rosunit',  # ros
             'rospack', 'std_msgs', 'message_runtime', 'message_generation', 'gencpp', 'genlisp', 'genpy', 'genmsg', 'catkin',
diff --git a/utilities/xmlrpcpp/CHANGELOG.rst b/utilities/xmlrpcpp/CHANGELOG.rst
index 2b8a7bc..8880e16 100644
--- a/utilities/xmlrpcpp/CHANGELOG.rst
+++ b/utilities/xmlrpcpp/CHANGELOG.rst
@@ -2,6 +2,17 @@
 Changelog for package xmlrpcpp
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
+1.13.1 (2017-07-27)
+-------------------
+* switch to libb64 for base64 encoding/decoding (`#1046 <https://github.com/ros/ros_comm/issues/1046>`_)
+
+1.13.0 (2017-02-22)
+-------------------
+
+1.12.7 (2017-02-17)
+-------------------
+* move headers to include/xmlrpcpp (`#962 <https://github.com/ros/ros_comm/issues/962>`_)
+
 1.12.6 (2016-10-26)
 -------------------
 
diff --git a/utilities/xmlrpcpp/CMakeLists.txt b/utilities/xmlrpcpp/CMakeLists.txt
index dfcd0a5..f063500 100644
--- a/utilities/xmlrpcpp/CMakeLists.txt
+++ b/utilities/xmlrpcpp/CMakeLists.txt
@@ -6,13 +6,20 @@ if(NOT WIN32)
 endif()
 
 find_package(catkin REQUIRED COMPONENTS cpp_common)
+
+# The CFG_EXTRAS is only for compatibility, to be removed in Lunar.
 catkin_package(
   INCLUDE_DIRS include
   LIBRARIES xmlrpcpp
   CATKIN_DEPENDS cpp_common
+  CFG_EXTRAS xmlrpcpp-extras.cmake
 )
 
-include_directories(include ${catkin_INCLUDE_DIRS})
+include_directories(
+  include
+  libb64/include
+  ${catkin_INCLUDE_DIRS}
+)
 link_directories(${catkin_LIBRARY_DIRS})
 
 if(WIN32)
@@ -29,14 +36,15 @@ add_library(xmlrpcpp
   src/XmlRpcSource.cpp
   src/XmlRpcUtil.cpp
   src/XmlRpcValue.cpp
-  )
+  libb64/src/cdecode.c
+  libb64/src/cencode.c
+)
 
 if(WIN32)
   target_link_libraries(xmlrpcpp ws2_32)
 endif()
 
-# FIXME the headers should be in a package-specific subfolder but can not be for backward compatibility
-install(DIRECTORY include/
+install(DIRECTORY include/${PROJECT_NAME}
   DESTINATION ${CATKIN_GLOBAL_INCLUDE_DESTINATION}
   FILES_MATCHING PATTERN "*.h")
 
@@ -44,3 +52,7 @@ install(TARGETS xmlrpcpp
   ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
   LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
   RUNTIME DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION})
+
+if (CATKIN_ENABLE_TESTING)
+  add_subdirectory(test)
+endif()
diff --git a/utilities/xmlrpcpp/cmake/xmlrpcpp-extras.cmake.in b/utilities/xmlrpcpp/cmake/xmlrpcpp-extras.cmake.in
new file mode 100644
index 0000000..8920356
--- /dev/null
+++ b/utilities/xmlrpcpp/cmake/xmlrpcpp-extras.cmake.in
@@ -0,0 +1 @@
+list(APPEND @PROJECT_NAME at _INCLUDE_DIRS "${@PROJECT_NAME at _DIR}/../../../@CATKIN_GLOBAL_INCLUDE_DESTINATION@/xmlrpcpp")
diff --git a/utilities/xmlrpcpp/include/base64.h b/utilities/xmlrpcpp/include/base64.h
deleted file mode 100644
index c239403..0000000
--- a/utilities/xmlrpcpp/include/base64.h
+++ /dev/null
@@ -1,380 +0,0 @@
-
-
-//  base64.hpp 
-//  Autor Konstantin Pilipchuk
-//  mailto:lostd at ukr.net
-//
-//
-
-#if !defined(__BASE64_H_INCLUDED__)
-#define __BASE64_H_INCLUDED__ 1
-
-#ifndef MAKEDEPEND
-# include <iterator>
-#endif
-
-#include <ios>
-
-static
-int _base64Chars[]= {'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
-				     'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z',
-			         '0','1','2','3','4','5','6','7','8','9',
-			         '+','/' };
-
-
-#define _0000_0011 0x03
-#define _1111_1100 0xFC
-#define _1111_0000 0xF0
-#define _0011_0000 0x30
-#define _0011_1100 0x3C
-#define _0000_1111 0x0F
-#define _1100_0000 0xC0
-#define _0011_1111 0x3F
-
-#define _EQUAL_CHAR   (-1)
-#define _UNKNOWN_CHAR (-2)
-
-#define _IOS_FAILBIT   std::ios_base::failbit
-#define _IOS_EOFBIT    std::ios_base::eofbit
-#define _IOS_BADBIT    std::ios_base::badbit
-#define _IOS_GOODBIT   std::ios_base::goodbit
-
-// TEMPLATE CLASS base64_put
-template<class _E = char, class _Tr = std::char_traits<_E> >
-class base64
-{
-public:
-
-	typedef unsigned char byte_t;
-	typedef _E            char_type;
-	typedef _Tr           traits_type; 
-
-	// base64 requires max line length <= 72 characters
-	// you can fill end of line
-	// it may be crlf, crlfsp, noline or other class like it
-
-
-	struct crlf
-	{
-		template<class _OI>
-			_OI operator()(_OI _To) const{
-			*_To = _Tr::to_char_type('\r'); ++_To;
-			*_To = _Tr::to_char_type('\n'); ++_To;
-
-			return (_To);
-		}
-	};
-
-
-	struct crlfsp
-	{
-		template<class _OI>
-			_OI operator()(_OI _To) const{
-			*_To = _Tr::to_char_type('\r'); ++_To;
-			*_To = _Tr::to_char_type('\n'); ++_To;
-			*_To = _Tr::to_char_type(' '); ++_To;
-
-			return (_To);
-		}
-	};
-
-	struct noline
-	{
-		template<class _OI>
-			_OI operator()(_OI _To) const{
-			return (_To);
-		}
-	};
-
-	struct three2four
-	{
-		void zero()
-		{
-			_data[0] = 0;
-			_data[1] = 0;
-			_data[2] = 0;
-		}
-
-		byte_t get_0()	const
-		{
-			return _data[0];
-		}
-		byte_t get_1()	const
-		{
-			return _data[1];
-		}
-		byte_t get_2()	const
-		{
-			return _data[2];
-		}
-
-		void set_0(byte_t _ch)
-		{
-			_data[0] = _ch;
-		}
-
-		void set_1(byte_t _ch)
-		{
-			_data[1] = _ch;
-		}
-
-		void set_2(byte_t _ch)
-		{
-			_data[2] = _ch;
-		}
-
-		// 0000 0000  1111 1111  2222 2222
-		// xxxx xxxx  xxxx xxxx  xxxx xxxx
-		// 0000 0011  1111 2222  2233 3333
-
-		int b64_0()	const	{return (_data[0] & _1111_1100) >> 2;}
-		int b64_1()	const	{return ((_data[0] & _0000_0011) << 4) + ((_data[1] & _1111_0000)>>4);}
-		int b64_2()	const	{return ((_data[1] & _0000_1111) << 2) + ((_data[2] & _1100_0000)>>6);}
-		int b64_3()	const	{return (_data[2] & _0011_1111);}
-
-		void b64_0(int _ch)	{_data[0] = ((_ch & _0011_1111) << 2) | (_0000_0011 & _data[0]);}
-
-		void b64_1(int _ch)	{
-			_data[0] = ((_ch & _0011_0000) >> 4) | (_1111_1100 & _data[0]);
-			_data[1] = ((_ch & _0000_1111) << 4) | (_0000_1111 & _data[1]);	}
-
-		void b64_2(int _ch)	{
-			_data[1] = ((_ch & _0011_1100) >> 2) | (_1111_0000 & _data[1]);
-			_data[2] = ((_ch & _0000_0011) << 6) | (_0011_1111 & _data[2]);	}
-
-		void b64_3(int _ch){
-			_data[2] = (_ch & _0011_1111) | (_1100_0000 & _data[2]);}
-
-	private:
-		byte_t _data[3];
-
-	};
-
-
-
-
-	template<class _II, class _OI, class _State, class _Endline>
-        _II put(_II _First, _II _Last, _OI _To, _State&, _Endline)  const
-	{
-		three2four _3to4;
-		int line_octets = 0;
-
-		while(_First != _Last)
-		{
-			_3to4.zero();
-
-			_3to4.set_0(*_First);
-			_First++;
-
-			if(_First == _Last)
-			{
-				*_To = _Tr::to_char_type(_base64Chars[_3to4.b64_0()]); ++_To;
-				*_To = _Tr::to_char_type(_base64Chars[_3to4.b64_1()]); ++_To;
-				*_To = _Tr::to_char_type('='); ++_To;
-				*_To = _Tr::to_char_type('='); ++_To;
-				goto __end;
-			}
-
-			_3to4.set_1(*_First);
-			_First++;
-
-			if(_First == _Last)
-			{
-				*_To = _Tr::to_char_type(_base64Chars[_3to4.b64_0()]); ++_To;
-				*_To = _Tr::to_char_type(_base64Chars[_3to4.b64_1()]); ++_To;
-				*_To = _Tr::to_char_type(_base64Chars[_3to4.b64_2()]); ++_To;
-				*_To = _Tr::to_char_type('='); ++_To;
-				goto __end;
-			}
-
-			_3to4.set_2(*_First);
-			_First++;
-
-			*_To = _Tr::to_char_type(_base64Chars[_3to4.b64_0()]); ++_To;
-			*_To = _Tr::to_char_type(_base64Chars[_3to4.b64_1()]); ++_To;
-			*_To = _Tr::to_char_type(_base64Chars[_3to4.b64_2()]); ++_To;
-			*_To = _Tr::to_char_type(_base64Chars[_3to4.b64_3()]); ++_To;
-
-			if(line_octets == 17)
-			{
-                                //_To = _Endl(_To);
-                                *_To = '\n'; ++_To;
-                                line_octets = 0;
-			}
-			else
-				++line_octets;
-		}
-
-		__end: ;
-
-		return (_First);
-
-	}
-
-
-	template<class _II, class _OI, class _State>
-		_II get(_II _First, _II _Last, _OI _To, _State& _St) const
-	{
-		three2four _3to4;
-		int _Char;
-
-		while(_First != _Last)
-		{
-
-			// Take octet
-			_3to4.zero();
-
-			// -- 0 --
-			// Search next valid char... 
-			while((_Char =  _getCharType(*_First)) < 0 && _Char == _UNKNOWN_CHAR)
-			{
-				if(++_First == _Last)
-				{
-					_St |= _IOS_FAILBIT|_IOS_EOFBIT; return _First; // unexpected EOF
-				}
-			}
-
-			if(_Char == _EQUAL_CHAR){
-				// Error! First character in octet can't be '='
-				_St |= _IOS_FAILBIT; 
-				return _First; 
-			}
-			else
-				_3to4.b64_0(_Char);
-
-
-			// -- 1 --
-			// Search next valid char... 
-			while(++_First != _Last)
-				if((_Char = _getCharType(*_First)) != _UNKNOWN_CHAR)
-					break;
-
-			if(_First == _Last)	{
-				_St |= _IOS_FAILBIT|_IOS_EOFBIT; // unexpected EOF 
-				return _First;
-			}
-
-			if(_Char == _EQUAL_CHAR){
-				// Error! Second character in octet can't be '='
-				_St |= _IOS_FAILBIT; 
-				return _First; 
-			}
-			else
-				_3to4.b64_1(_Char);
-
-
-			// -- 2 --
-			// Search next valid char... 
-			while(++_First != _Last)
-				if((_Char = _getCharType(*_First)) != _UNKNOWN_CHAR)
-					break;
-
-			if(_First == _Last)	{
-				// Error! Unexpected EOF. Must be '=' or base64 character
-				_St |= _IOS_FAILBIT|_IOS_EOFBIT; 
-				return _First; 
-			}
-
-			if(_Char == _EQUAL_CHAR){
-				// OK!
-				_3to4.b64_2(0); 
-				_3to4.b64_3(0); 
-
-				// chek for EOF
-				if(++_First == _Last)
-				{
-					// Error! Unexpected EOF. Must be '='. Ignore it.
-					//_St |= _IOS_BADBIT|_IOS_EOFBIT;
-					_St |= _IOS_EOFBIT;
-				}
-				else 
-					if(_getCharType(*_First) != _EQUAL_CHAR)
-					{
-						// Error! Must be '='. Ignore it.
-						//_St |= _IOS_BADBIT;
-					}
-				else
-					++_First; // Skip '='
-
-				// write 1 byte to output
-				*_To = (byte_t) _3to4.get_0();
-				return _First;
-			}
-			else
-				_3to4.b64_2(_Char);
-
-
-			// -- 3 --
-			// Search next valid char... 
-			while(++_First != _Last)
-				if((_Char = _getCharType(*_First)) != _UNKNOWN_CHAR)
-					break;
-
-			if(_First == _Last)	{
-				// Unexpected EOF. It's error. But ignore it.
-				//_St |= _IOS_FAILBIT|_IOS_EOFBIT; 
-					_St |= _IOS_EOFBIT; 
-				
-				return _First; 
-			}
-
-			if(_Char == _EQUAL_CHAR)
-			{
-				// OK!
-				_3to4.b64_3(0); 
-
-				// write to output 2 bytes
-				*_To = (byte_t) _3to4.get_0();
-				*_To = (byte_t) _3to4.get_1();
-
-				++_First; // set position to next character
-
-				return _First;
-			}
-			else
-				_3to4.b64_3(_Char);
-
-
-			// write to output 3 bytes
-			*_To = (byte_t) _3to4.get_0();
-			*_To = (byte_t) _3to4.get_1();
-			*_To = (byte_t) _3to4.get_2();
-
-			++_First;
-			
-
-		} // while(_First != _Last)
-
-		return (_First);
-	}
-
-protected:
-	
-	int _getCharType(int _Ch) const
-	{
-		if(_base64Chars[62] == _Ch)
-			return 62;
-
-		if(_base64Chars[63] == _Ch)
-			return 63;
-
-		if((_base64Chars[0] <= _Ch) && (_base64Chars[25] >= _Ch))
-			return _Ch - _base64Chars[0];
-
-		if((_base64Chars[26] <= _Ch) && (_base64Chars[51] >= _Ch))
-			return _Ch - _base64Chars[26] + 26;
-
-		if((_base64Chars[52] <= _Ch) && (_base64Chars[61] >= _Ch))
-			return _Ch - _base64Chars[52] + 52;
-
-		if(_Ch == _Tr::to_int_type('='))
-			return _EQUAL_CHAR;
-
-		return _UNKNOWN_CHAR;
-	}
-
-
-};
-
-
-#endif
diff --git a/utilities/xmlrpcpp/include/XmlRpc.h b/utilities/xmlrpcpp/include/xmlrpcpp/XmlRpc.h
similarity index 93%
rename from utilities/xmlrpcpp/include/XmlRpc.h
rename to utilities/xmlrpcpp/include/xmlrpcpp/XmlRpc.h
index 6b00b18..9fd626a 100644
--- a/utilities/xmlrpcpp/include/XmlRpc.h
+++ b/utilities/xmlrpcpp/include/xmlrpcpp/XmlRpc.h
@@ -27,12 +27,12 @@
 # include <string>
 #endif
 
-#include "XmlRpcClient.h"
-#include "XmlRpcException.h"
-#include "XmlRpcServer.h"
-#include "XmlRpcServerMethod.h"
-#include "XmlRpcValue.h"
-#include "XmlRpcUtil.h"
+#include "xmlrpcpp/XmlRpcClient.h"
+#include "xmlrpcpp/XmlRpcException.h"
+#include "xmlrpcpp/XmlRpcServer.h"
+#include "xmlrpcpp/XmlRpcServerMethod.h"
+#include "xmlrpcpp/XmlRpcValue.h"
+#include "xmlrpcpp/XmlRpcUtil.h"
 
 #include <stdexcept>
 
diff --git a/utilities/xmlrpcpp/include/XmlRpcClient.h b/utilities/xmlrpcpp/include/xmlrpcpp/XmlRpcClient.h
similarity index 97%
rename from utilities/xmlrpcpp/include/XmlRpcClient.h
rename to utilities/xmlrpcpp/include/xmlrpcpp/XmlRpcClient.h
index 6f47778..2154b39 100644
--- a/utilities/xmlrpcpp/include/XmlRpcClient.h
+++ b/utilities/xmlrpcpp/include/xmlrpcpp/XmlRpcClient.h
@@ -13,9 +13,9 @@
 # include <string>
 #endif
 
-#include "XmlRpcDispatch.h"
-#include "XmlRpcSource.h"
-#include "XmlRpcDecl.h"
+#include "xmlrpcpp/XmlRpcDispatch.h"
+#include "xmlrpcpp/XmlRpcSource.h"
+#include "xmlrpcpp/XmlRpcDecl.h"
 
 namespace XmlRpc {
 
diff --git a/utilities/xmlrpcpp/include/XmlRpcDecl.h b/utilities/xmlrpcpp/include/xmlrpcpp/XmlRpcDecl.h
similarity index 100%
rename from utilities/xmlrpcpp/include/XmlRpcDecl.h
rename to utilities/xmlrpcpp/include/xmlrpcpp/XmlRpcDecl.h
diff --git a/utilities/xmlrpcpp/include/XmlRpcDispatch.h b/utilities/xmlrpcpp/include/xmlrpcpp/XmlRpcDispatch.h
similarity index 98%
rename from utilities/xmlrpcpp/include/XmlRpcDispatch.h
rename to utilities/xmlrpcpp/include/xmlrpcpp/XmlRpcDispatch.h
index 12b01ad..5e90822 100644
--- a/utilities/xmlrpcpp/include/XmlRpcDispatch.h
+++ b/utilities/xmlrpcpp/include/xmlrpcpp/XmlRpcDispatch.h
@@ -8,7 +8,7 @@
 # pragma warning(disable:4786)    // identifier was truncated in debug info
 #endif
 
-#include "XmlRpcDecl.h"
+#include "xmlrpcpp/XmlRpcDecl.h"
 
 #ifndef MAKEDEPEND
 # include <list>
diff --git a/utilities/xmlrpcpp/include/XmlRpcException.h b/utilities/xmlrpcpp/include/xmlrpcpp/XmlRpcException.h
similarity index 96%
rename from utilities/xmlrpcpp/include/XmlRpcException.h
rename to utilities/xmlrpcpp/include/xmlrpcpp/XmlRpcException.h
index bff5bf2..4e8a2a6 100644
--- a/utilities/xmlrpcpp/include/XmlRpcException.h
+++ b/utilities/xmlrpcpp/include/xmlrpcpp/XmlRpcException.h
@@ -12,7 +12,7 @@
 # include <string>
 #endif
 
-#include "XmlRpcDecl.h"
+#include "xmlrpcpp/XmlRpcDecl.h"
 
 
 namespace XmlRpc {
diff --git a/utilities/xmlrpcpp/include/XmlRpcServer.h b/utilities/xmlrpcpp/include/xmlrpcpp/XmlRpcServer.h
similarity index 96%
rename from utilities/xmlrpcpp/include/XmlRpcServer.h
rename to utilities/xmlrpcpp/include/xmlrpcpp/XmlRpcServer.h
index 035d383..ac16dae 100644
--- a/utilities/xmlrpcpp/include/XmlRpcServer.h
+++ b/utilities/xmlrpcpp/include/xmlrpcpp/XmlRpcServer.h
@@ -16,9 +16,9 @@
 # include <string>
 #endif
 
-#include "XmlRpcDispatch.h"
-#include "XmlRpcSource.h"
-#include "XmlRpcDecl.h"
+#include "xmlrpcpp/XmlRpcDispatch.h"
+#include "xmlrpcpp/XmlRpcSource.h"
+#include "xmlrpcpp/XmlRpcDecl.h"
 
 namespace XmlRpc {
 
diff --git a/utilities/xmlrpcpp/include/XmlRpcServerConnection.h b/utilities/xmlrpcpp/include/xmlrpcpp/XmlRpcServerConnection.h
similarity index 96%
rename from utilities/xmlrpcpp/include/XmlRpcServerConnection.h
rename to utilities/xmlrpcpp/include/xmlrpcpp/XmlRpcServerConnection.h
index f5c224d..ed4d092 100644
--- a/utilities/xmlrpcpp/include/XmlRpcServerConnection.h
+++ b/utilities/xmlrpcpp/include/xmlrpcpp/XmlRpcServerConnection.h
@@ -11,9 +11,9 @@
 # include <string>
 #endif
 
-#include "XmlRpcValue.h"
-#include "XmlRpcSource.h"
-#include "XmlRpcDecl.h"
+#include "xmlrpcpp/XmlRpcValue.h"
+#include "xmlrpcpp/XmlRpcSource.h"
+#include "xmlrpcpp/XmlRpcDecl.h"
 
 namespace XmlRpc {
 
diff --git a/utilities/xmlrpcpp/include/XmlRpcServerMethod.h b/utilities/xmlrpcpp/include/xmlrpcpp/XmlRpcServerMethod.h
similarity index 97%
rename from utilities/xmlrpcpp/include/XmlRpcServerMethod.h
rename to utilities/xmlrpcpp/include/xmlrpcpp/XmlRpcServerMethod.h
index 7b7ddca..90dddcd 100644
--- a/utilities/xmlrpcpp/include/XmlRpcServerMethod.h
+++ b/utilities/xmlrpcpp/include/xmlrpcpp/XmlRpcServerMethod.h
@@ -8,7 +8,7 @@
 # pragma warning(disable:4786)    // identifier was truncated in debug info
 #endif
 
-#include "XmlRpcDecl.h"
+#include "xmlrpcpp/XmlRpcDecl.h"
 
 #ifndef MAKEDEPEND
 # include <string>
diff --git a/utilities/xmlrpcpp/include/XmlRpcSocket.h b/utilities/xmlrpcpp/include/xmlrpcpp/XmlRpcSocket.h
similarity index 98%
rename from utilities/xmlrpcpp/include/XmlRpcSocket.h
rename to utilities/xmlrpcpp/include/xmlrpcpp/XmlRpcSocket.h
index 711a520..bc9a530 100644
--- a/utilities/xmlrpcpp/include/XmlRpcSocket.h
+++ b/utilities/xmlrpcpp/include/xmlrpcpp/XmlRpcSocket.h
@@ -15,7 +15,7 @@
 # include <string>
 #endif
 
-#include "XmlRpcDecl.h"
+#include "xmlrpcpp/XmlRpcDecl.h"
 
 namespace XmlRpc {
 
diff --git a/utilities/xmlrpcpp/include/XmlRpcSource.h b/utilities/xmlrpcpp/include/xmlrpcpp/XmlRpcSource.h
similarity index 98%
rename from utilities/xmlrpcpp/include/XmlRpcSource.h
rename to utilities/xmlrpcpp/include/xmlrpcpp/XmlRpcSource.h
index f82ccb1..217f416 100644
--- a/utilities/xmlrpcpp/include/XmlRpcSource.h
+++ b/utilities/xmlrpcpp/include/xmlrpcpp/XmlRpcSource.h
@@ -8,7 +8,7 @@
 # pragma warning(disable:4786)    // identifier was truncated in debug info
 #endif
 
-#include "XmlRpcDecl.h"
+#include "xmlrpcpp/XmlRpcDecl.h"
 
 namespace XmlRpc {
 
diff --git a/utilities/xmlrpcpp/include/XmlRpcUtil.h b/utilities/xmlrpcpp/include/xmlrpcpp/XmlRpcUtil.h
similarity index 98%
rename from utilities/xmlrpcpp/include/XmlRpcUtil.h
rename to utilities/xmlrpcpp/include/xmlrpcpp/XmlRpcUtil.h
index 78627f4..acde160 100644
--- a/utilities/xmlrpcpp/include/XmlRpcUtil.h
+++ b/utilities/xmlrpcpp/include/xmlrpcpp/XmlRpcUtil.h
@@ -11,7 +11,7 @@
 # include <string>
 #endif
 
-#include "XmlRpcDecl.h"
+#include "xmlrpcpp/XmlRpcDecl.h"
 
 #if defined(_MSC_VER)
 # define snprintf	    _snprintf_s
diff --git a/utilities/xmlrpcpp/include/XmlRpcValue.h b/utilities/xmlrpcpp/include/xmlrpcpp/XmlRpcValue.h
similarity index 99%
rename from utilities/xmlrpcpp/include/XmlRpcValue.h
rename to utilities/xmlrpcpp/include/xmlrpcpp/XmlRpcValue.h
index fe6cb8c..0d72c59 100644
--- a/utilities/xmlrpcpp/include/XmlRpcValue.h
+++ b/utilities/xmlrpcpp/include/xmlrpcpp/XmlRpcValue.h
@@ -8,7 +8,7 @@
 # pragma warning(disable:4786)    // identifier was truncated in debug info
 #endif
 
-#include "XmlRpcDecl.h"
+#include "xmlrpcpp/XmlRpcDecl.h"
 
 #ifndef MAKEDEPEND
 # include <map>
diff --git a/utilities/xmlrpcpp/include/xmlrpcpp/base64.h b/utilities/xmlrpcpp/include/xmlrpcpp/base64.h
new file mode 100644
index 0000000..f51244c
--- /dev/null
+++ b/utilities/xmlrpcpp/include/xmlrpcpp/base64.h
@@ -0,0 +1,3 @@
+#error This header was removed due to licensing issues. \
+Please use a dedicated base64 library if you need one for your own project. \
+See https://github.com/ros/ros_comm/pull/1046 for more details.
diff --git a/utilities/xmlrpcpp/libb64/AUTHORS b/utilities/xmlrpcpp/libb64/AUTHORS
new file mode 100644
index 0000000..bf4a9f4
--- /dev/null
+++ b/utilities/xmlrpcpp/libb64/AUTHORS
@@ -0,0 +1,15 @@
+libb64: Base64 Encoding/Decoding Routines
+======================================
+
+Authors:
+-------
+
+Chris Venter	chris.venter at gmail.com	http://controlaltfire.com
+
+Contributors:
+------------
+
+Mario Rugiero
+Shlok Datye
+Peter K. Lee
+
diff --git a/utilities/xmlrpcpp/libb64/BENCHMARKS b/utilities/xmlrpcpp/libb64/BENCHMARKS
new file mode 100644
index 0000000..fd34056
--- /dev/null
+++ b/utilities/xmlrpcpp/libb64/BENCHMARKS
@@ -0,0 +1,85 @@
+-- Intro
+
+Some people have expressed opinions about how
+fast libb64's encoding and decoding routines
+are, as compared to some other BASE64 packages
+out there.
+
+This document shows the result of a short and sweet 
+benchmark, which takes a large-ish file and 
+encodes/decodes it a number of times.
+The winner is the executable that does this task the quickest.
+
+-- Platform
+
+The tests were all run on a Fujitsu-Siemens laptop,
+with a Pentium M processor running at 2GHz, with
+1GB of RAM, running Ubuntu 10.4.
+
+-- Packages
+
+The following BASE64 packages were used in this benchmark:
+
+- libb64-1.2 (libb64-base64)
+  From libb64.sourceforge.net
+  Size of executable: 18808 bytes
+  Compiled with:
+    CFLAGS += -O3
+    BUFFERSIZE = 16777216
+
+- base64-1.5 (fourmilab-base64)
+  From http://www.fourmilab.ch/webtools/base64/
+  Size of executable: 20261 bytes
+  Compiled with Default package settings
+
+- coreutils 7.4-2ubuntu2 (coreutils-base64)
+  From http://www.gnu.org/software/coreutils/
+  Size of executable: 38488 bytes
+  Default binary distributed with Ubuntu 10.4
+
+-- Input File
+
+Using blender-2.49b-linux-glibc236-py25-i386.tar.bz2
+from http://www.blender.org/download/get-blender/
+Size: 18285329 bytes
+(approx. 18MB)
+
+-- Method
+
+Encode and Decode the Input file 50 times in a loop,
+using a simple shell script, and get the running time.
+
+-- Results
+
+$ time ./benchmark-libb64.sh 
+real	0m28.389s
+user	0m14.077s
+sys	0m12.309s
+
+$ time ./benchmark-fourmilab.sh 
+real	1m43.160s
+user	1m23.769s
+sys	0m8.737s
+
+$ time ./benchmark-coreutils.sh 
+real	0m36.288s
+user	0m24.746s
+sys	0m8.181s
+
+28.389 for 18MB * 50
+= 28.389 for 900
+
+-- Conclusion
+
+libb64 is the fastest encoder/decoder, and 
+has the smallest executable size.
+
+On average it will encode and decode at roughly 31.7MB/second.
+
+The closest "competitor" is base64 from GNU coreutils, which
+reaches only 24.8MB/second.
+
+--
+14/06/2010
+chris.venter at gmail.com
+
diff --git a/utilities/xmlrpcpp/libb64/CHANGELOG b/utilities/xmlrpcpp/libb64/CHANGELOG
new file mode 100644
index 0000000..c1c0844
--- /dev/null
+++ b/utilities/xmlrpcpp/libb64/CHANGELOG
@@ -0,0 +1,33 @@
+libb64: Base64 Encoding/Decoding Routines
+======================================
+
+## Changelog ##
+
+Version 1.2.1 Release
+---------------------
+Fixed a long-standing bug in src/cdecode.c where value_in was not correctly
+checked against the bounds [0..decoding_size)
+Thanks to both Mario Rugiero and Shlok Datye for pointing this out.
+Added some simple example code to answer some of the most common misconceptions
+people have about the library usage.
+
+Version 1.2 Release
+-------------------
+Removed the b64dec, b64enc, encoder and decoder programs in favour of
+a better example, called base64, which encodes and decodes 
+depending on its arguments.
+
+Created a solution for Microsoft Visual Studio C++ Express 2010
+edition, which simply builds the base64 example as a console application.
+
+Version 1.1 Release
+-------------------
+Modified encode.h to (correctly) read from the iostream argument,
+instead of std::cin.
+Thanks to Peter K. Lee for the heads-up.
+
+No API changes.
+
+Version 1.0 Release
+-------------------
+The current content is the changeset.
diff --git a/utilities/xmlrpcpp/libb64/INSTALL b/utilities/xmlrpcpp/libb64/INSTALL
new file mode 100644
index 0000000..b05f5db
--- /dev/null
+++ b/utilities/xmlrpcpp/libb64/INSTALL
@@ -0,0 +1,44 @@
+libb64: Base64 Encoding/Decoding Routines
+======================================
+
+Requirements:
+------------
+This piece of software has minimal requirements.
+
+I have tested it on the following systems:
+
+- a Linux machine, with the following specs:
+(this was the original development machine)
+	* FedoraCore 4
+	* kernel v. 2.6.11 (stock FC4 kernel)
+	* gcc version 4.0.1 20050727 (Red Hat 4.0.1-5)
+	* glibc-2.3.5-10
+	* make v. 3.80
+	* some arb version of makedepend
+
+- Windows XP machine
+	* MSYS 1.0
+	* MinGW 5.1.4
+	* gcc version 3.4.5 (mingw-vista special r3)
+
+- Windows XP machine (same as above)
+	* Microsoft Visual Studio 2010, Version 10.0.30319.1 RTMRel
+	
+Barring any serious screwups on my part, this code should compile and run sweetly
+under Cygwin and other systems too. If you DO get it running under some weird arch/os setup,
+send me a mail, please.
+
+Compiling:
+---------
+There is no configure. It would be overkill for something so simple...
+Run make in the root directory.
+
+Installing:
+----------
+Since the current targets are a standalone executable and a static library
+(fancy name for archive) with some headers, an install script has not been implemented yet.
+Simply copy the executable into your path, and use it.
+
+--
+peace out
+Chris
diff --git a/utilities/xmlrpcpp/libb64/LICENSE b/utilities/xmlrpcpp/libb64/LICENSE
new file mode 100644
index 0000000..a6b5606
--- /dev/null
+++ b/utilities/xmlrpcpp/libb64/LICENSE
@@ -0,0 +1,29 @@
+Copyright-Only Dedication (based on United States law) 
+or Public Domain Certification
+
+The person or persons who have associated work with this document (the
+"Dedicator" or "Certifier") hereby either (a) certifies that, to the best of
+his knowledge, the work of authorship identified is in the public domain of the
+country from which the work is published, or (b) hereby dedicates whatever
+copyright the dedicators holds in the work of authorship identified below (the
+"Work") to the public domain. A certifier, moreover, dedicates any copyright
+interest he may have in the associated work, and for these purposes, is
+described as a "dedicator" below.
+
+A certifier has taken reasonable steps to verify the copyright status of this
+work. Certifier recognizes that his good faith efforts may not shield him from
+liability if in fact the work certified is not in the public domain.
+
+Dedicator makes this dedication for the benefit of the public at large and to
+the detriment of the Dedicator's heirs and successors. Dedicator intends this
+dedication to be an overt act of relinquishment in perpetuity of all present
+and future rights under copyright law, whether vested or contingent, in the
+Work. Dedicator understands that such relinquishment of all rights includes
+the relinquishment of all rights to enforce (by lawsuit or otherwise) those
+copyrights in the Work.
+
+Dedicator recognizes that, once placed in the public domain, the Work may be
+freely reproduced, distributed, transmitted, used, modified, built upon, or
+otherwise exploited by anyone for any purpose, commercial or non-commercial,
+and in any way, including by methods that have not yet been invented or
+conceived.
\ No newline at end of file
diff --git a/utilities/xmlrpcpp/libb64/Makefile b/utilities/xmlrpcpp/libb64/Makefile
new file mode 100644
index 0000000..db40356
--- /dev/null
+++ b/utilities/xmlrpcpp/libb64/Makefile
@@ -0,0 +1,31 @@
+all: all_src all_base64 all_examples
+
+all_src:
+	$(MAKE) -C src
+all_base64: all_src
+	$(MAKE) -C base64
+all_examples:
+	$(MAKE) -C examples
+	
+clean: clean_src clean_base64 clean_include clean_examples
+	rm -f *~ *.bak
+
+clean_include:
+	rm -f include/b64/*~
+
+clean_src:
+	$(MAKE) -C src clean;
+clean_base64:
+	$(MAKE) -C base64 clean;
+clean_examples:
+	$(MAKE) -C examples clean;
+		
+distclean: clean distclean_src distclean_base64 distclean_examples
+
+distclean_src:
+	$(MAKE) -C src distclean;
+distclean_base64:
+	$(MAKE) -C base64 distclean;
+distclean_examples:
+	$(MAKE) -C examples distclean;
+
diff --git a/utilities/xmlrpcpp/libb64/README b/utilities/xmlrpcpp/libb64/README
new file mode 100644
index 0000000..132f02f
--- /dev/null
+++ b/utilities/xmlrpcpp/libb64/README
@@ -0,0 +1,143 @@
+b64: Base64 Encoding/Decoding Routines
+======================================
+
+Overview:
+--------
+libb64 is a library of ANSI C routines for fast encoding/decoding data into and
+from a base64-encoded format. C++ wrappers are included, as well as the source
+code for standalone encoding and decoding executables.
+
+base64 consists of ASCII text, and is therefore a useful encoding for storing 
+binary data in a text file, such as xml, or sending binary data over text-only
+email.
+
+References:
+----------
+* Wikipedia article:
+	http://en.wikipedia.org/wiki/Base64
+* base64, another implementation of a commandline en/decoder:
+	http://www.fourmilab.ch/webtools/base64/
+
+Why?
+---
+I did this because I need an implementation of base64 encoding and decoding,
+without any licensing problems. Most OS implementations are released under
+either the GNU/GPL, or a BSD-variant, which is not what I require.
+
+Also, the chance to actually use the co-routine implementation in code is rare,
+and its use here is fitting. I couldn't pass up the chance.
+For more information on this technique, see "Coroutines in C", by Simon Tatham,
+which can be found online here: 
+http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html
+
+So then, under which license do I release this code? On to the next section...
+
+License:
+-------
+This work is released under into the Public Domain.
+It basically boils down to this: I put this work in the public domain, and you
+can take it and do whatever you want with it.
+
+An example of this "license" is the Creative Commons Public Domain License, a
+copy of which can be found in the LICENSE file, and also online at
+http://creativecommons.org/licenses/publicdomain/
+
+Commandline Use:
+---------------
+There is a new executable available, it is simply called base64.
+It can encode and decode files, as instructed by the user.
+
+To encode a file:
+$ ./base64 -e filea fileb
+fileb will now be the base64-encoded version of filea.
+
+To decode a file:
+$ ./base64 -d fileb filec
+filec will now be identical to filea.
+
+Programming:
+-----------
+Some C++ wrappers are provided as well, so you don't have to get your hands
+dirty. Encoding from standard input to standard output is as simple as
+
+	#include <b64/encode.h>
+	#include <iostream>
+	int main()
+	{
+		base64::encoder E;
+		E.encode(std::cin, std::cout);
+		return 0;
+	}
+
+Both standalone executables and a static library is provided in the package,
+
+Example code:
+------------
+The 'examples' directory contains some simple example C code, that demonstrates
+how to use the C interface of the library.
+
+Implementation:
+--------------
+It is DAMN fast, if I may say so myself. The C code uses a little trick which
+has been used to implement coroutines, of which one can say that this
+implementation is an example.
+
+(To see how the libb64 codebase compares with some other BASE64 implementations
+available, see the BENCHMARKS file)
+
+The trick involves the fact that a switch-statement may legally cross into
+sub-blocks. A very thorough and enlightening essay on co-routines in C, using
+this method, can be found in the above mentioned "Coroutines in C", by Simon
+Tatham: http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html
+
+For example, an RLE decompressing routine, adapted from the article:
+1	static int STATE = 0;
+2	static int len, c;
+3	switch (STATE)
+4	{
+5		while (1)
+6		{
+7			c = getchar();
+8			if (c == EOF) return EOF;
+9			if (c == 0xFF) {
+10				len = getchar();
+11				c = getchar();
+12				while (len--)
+13				{
+14					STATE = 0;
+15					return c;
+16	case 0:
+17				}
+18			} else
+19				STATE = 1;
+20				return c;
+21	case 1:
+22			}
+23		}
+24	}
+
+As can be seen from this example, a coroutine depends on a state variable,
+which it sets directly before exiting (lines 14 and 119). The next time the
+routine is entered, the switch moves control to the specific point directly
+after the previous exit (lines 16 and 21).hands
+
+(As an aside, in the mentioned article the combination of the top-level switch,
+the various setting of the state, the return of a value, and the labelling of
+the exit point is wrapped in #define macros, making the structure of the
+routine even clearer.)
+
+The obvious problem with any such routine is the static keyword.
+Any static variables in a function spell doom for multithreaded applications.
+Also, in situations where this coroutine is used by more than one other
+coroutines, the consistency is disturbed.
+
+What is needed is a structure for storing these variabled, which is passed to
+the routine seperately. This obviously breaks the modularity of the function,
+since now the caller has to worry about and care for the internal state of the
+routine (the callee). This allows for a fast, multithreading-enabled
+implementation, which may (obviously) be wrapped in a C++ object for ease of
+use.
+
+The base64 encoding and decoding functionality in this package is implemented
+in exactly this way, providing both a high-speed high-maintanence C interface,
+and a wrapped C++ which is low-maintanence and only slightly less performant.
diff --git a/utilities/xmlrpcpp/libb64/TODO b/utilities/xmlrpcpp/libb64/TODO
new file mode 100644
index 0000000..e69de29
diff --git a/utilities/xmlrpcpp/libb64/include/b64/cdecode.h b/utilities/xmlrpcpp/libb64/include/b64/cdecode.h
new file mode 100644
index 0000000..5729853
--- /dev/null
+++ b/utilities/xmlrpcpp/libb64/include/b64/cdecode.h
@@ -0,0 +1,29 @@
+/*
+cdecode.h - c header for a base64 decoding algorithm
+
+This is part of the libb64 project, and has been placed in the public domain.
+For details, see http://sourceforge.net/projects/libb64
+*/
+
+#ifndef BASE64_CDECODE_H
+#define BASE64_CDECODE_H
+
+typedef enum
+{
+	step_a, step_b, step_c, step_d
+} base64_decodestep;
+
+typedef struct
+{
+	base64_decodestep step;
+	char plainchar;
+} base64_decodestate;
+
+void base64_init_decodestate(base64_decodestate* state_in);
+
+int base64_decode_value(char value_in);
+
+int base64_decode_block(const char* code_in, const int length_in, char* plaintext_out, base64_decodestate* state_in);
+
+#endif /* BASE64_CDECODE_H */
+
diff --git a/utilities/xmlrpcpp/libb64/include/b64/cencode.h b/utilities/xmlrpcpp/libb64/include/b64/cencode.h
new file mode 100644
index 0000000..cf32131
--- /dev/null
+++ b/utilities/xmlrpcpp/libb64/include/b64/cencode.h
@@ -0,0 +1,32 @@
+/*
+cencode.h - c header for a base64 encoding algorithm
+
+This is part of the libb64 project, and has been placed in the public domain.
+For details, see http://sourceforge.net/projects/libb64
+*/
+
+#ifndef BASE64_CENCODE_H
+#define BASE64_CENCODE_H
+
+typedef enum
+{
+	step_A, step_B, step_C
+} base64_encodestep;
+
+typedef struct
+{
+	base64_encodestep step;
+	char result;
+	int stepcount;
+} base64_encodestate;
+
+void base64_init_encodestate(base64_encodestate* state_in);
+
+char base64_encode_value(char value_in);
+
+int base64_encode_block(const char* plaintext_in, int length_in, char* code_out, base64_encodestate* state_in);
+
+int base64_encode_blockend(char* code_out, base64_encodestate* state_in);
+
+#endif /* BASE64_CENCODE_H */
+
diff --git a/utilities/xmlrpcpp/libb64/include/b64/decode.h b/utilities/xmlrpcpp/libb64/include/b64/decode.h
new file mode 100644
index 0000000..8fd0188
--- /dev/null
+++ b/utilities/xmlrpcpp/libb64/include/b64/decode.h
@@ -0,0 +1,72 @@
+// :mode=c++:
+/*
+decode.h - c++ wrapper for a base64 decoding algorithm
+
+This is part of the libb64 project, and has been placed in the public domain.
+For details, see http://sourceforge.net/projects/libb64
+*/
+#ifndef BASE64_DECODE_H
+#define BASE64_DECODE_H
+
+#include <iostream>
+
+namespace base64
+{
+	extern "C"
+	{
+		#include "cdecode.h"
+	}
+
+	struct decoder
+	{
+		base64_decodestate _state;
+		int _buffersize;
+
+		decoder(int buffersize_in = 512)
+		: _buffersize(buffersize_in)
+		{
+			base64_init_decodestate(&_state);
+		}
+
+		int decode(char value_in)
+		{
+			return base64_decode_value(value_in);
+		}
+
+		int decode(const char* code_in, const int length_in, char* plaintext_out)
+		{
+			return base64_decode_block(code_in, length_in, plaintext_out, &_state);
+		}
+
+		void decode(std::istream& istream_in, std::ostream& ostream_in)
+		{
+			base64_init_decodestate(&_state);
+			//
+			const int N = _buffersize;
+			char* code = new char[N];
+			char* plaintext = new char[N];
+			int codelength;
+			int plainlength;
+
+			do
+			{
+				istream_in.read((char*)code, N);
+				codelength = istream_in.gcount();
+				plainlength = decode(code, codelength, plaintext);
+				ostream_in.write((const char*)plaintext, plainlength);
+			}
+			while (istream_in.good() && codelength > 0);
+			//
+			base64_init_decodestate(&_state);
+
+			delete [] code;
+			delete [] plaintext;
+		}
+	};
+
+} // namespace base64
+
+
+
+#endif // BASE64_DECODE_H
+
diff --git a/utilities/xmlrpcpp/libb64/include/b64/encode.h b/utilities/xmlrpcpp/libb64/include/b64/encode.h
new file mode 100644
index 0000000..dc481b1
--- /dev/null
+++ b/utilities/xmlrpcpp/libb64/include/b64/encode.h
@@ -0,0 +1,79 @@
+// :mode=c++:
+/*
+encode.h - c++ wrapper for a base64 encoding algorithm
+
+This is part of the libb64 project, and has been placed in the public domain.
+For details, see http://sourceforge.net/projects/libb64
+*/
+#ifndef BASE64_ENCODE_H
+#define BASE64_ENCODE_H
+
+#include <iostream>
+
+namespace base64
+{
+	extern "C" 
+	{
+		#include "cencode.h"
+	}
+
+	struct encoder
+	{
+		base64_encodestate _state;
+		int _buffersize;
+
+		encoder(int buffersize_in = 512)
+		: _buffersize(buffersize_in)
+		{
+			base64_init_encodestate(&_state);
+		}
+
+		int encode(char value_in)
+		{
+			return base64_encode_value(value_in);
+		}
+
+		int encode(const char* code_in, const int length_in, char* plaintext_out)
+		{
+			return base64_encode_block(code_in, length_in, plaintext_out, &_state);
+		}
+
+		int encode_end(char* plaintext_out)
+		{
+			return base64_encode_blockend(plaintext_out, &_state);
+		}
+
+		void encode(std::istream& istream_in, std::ostream& ostream_in)
+		{
+			base64_init_encodestate(&_state);
+			//
+			const int N = _buffersize;
+			char* plaintext = new char[N];
+			char* code = new char[2*N];
+			int plainlength;
+			int codelength;
+
+			do
+			{
+				istream_in.read(plaintext, N);
+				plainlength = istream_in.gcount();
+				//
+				codelength = encode(plaintext, plainlength, code);
+				ostream_in.write(code, codelength);
+			}
+			while (istream_in.good() && plainlength > 0);
+
+			codelength = encode_end(code);
+			ostream_in.write(code, codelength);
+			//
+			base64_init_encodestate(&_state);
+
+			delete [] code;
+			delete [] plaintext;
+		}
+	};
+
+} // namespace base64
+
+#endif // BASE64_ENCODE_H
+
diff --git a/utilities/xmlrpcpp/libb64/src/Makefile b/utilities/xmlrpcpp/libb64/src/Makefile
new file mode 100644
index 0000000..28b2382
--- /dev/null
+++ b/utilities/xmlrpcpp/libb64/src/Makefile
@@ -0,0 +1,43 @@
+LIBRARIES = libb64.a
+
+# Build flags (uncomment one)
+#############################
+# Release build flags
+CFLAGS += -O3
+#############################
+# Debug build flags
+#CFLAGS += -g
+#############################
+
+SOURCES = cdecode.c  cencode.c
+
+TARGETS = $(LIBRARIES)
+
+LINK.o = gcc
+
+CFLAGS += -Werror -pedantic
+CFLAGS += -I../include
+
+vpath %.h ../include/b64
+
+.PHONY : clean
+
+all: $(TARGETS) #strip
+
+libb64.a: cencode.o cdecode.o
+	$(AR) $(ARFLAGS) $@ $^
+
+strip:
+	strip $(BINARIES) *.exe
+
+clean:
+	rm -f *.exe* *.o $(TARGETS) *.bak *~
+
+distclean: clean
+	rm -f depend
+
+depend: $(SOURCES)
+	makedepend -f- $(CFLAGS) $(SOURCES) 2> /dev/null 1> depend
+
+-include depend
+
diff --git a/utilities/xmlrpcpp/libb64/src/cdecode.c b/utilities/xmlrpcpp/libb64/src/cdecode.c
new file mode 100644
index 0000000..a6c0a42
--- /dev/null
+++ b/utilities/xmlrpcpp/libb64/src/cdecode.c
@@ -0,0 +1,88 @@
+/*
+cdecoder.c - c source to a base64 decoding algorithm implementation
+
+This is part of the libb64 project, and has been placed in the public domain.
+For details, see http://sourceforge.net/projects/libb64
+*/
+
+#include <b64/cdecode.h>
+
+int base64_decode_value(char value_in)
+{
+	static const char decoding[] = {62,-1,-1,-1,63,52,53,54,55,56,57,58,59,60,61,-1,-1,-1,-2,-1,-1,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1,-1,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51};
+	static const char decoding_size = sizeof(decoding);
+	value_in -= 43;
+	if (value_in < 0 || value_in >= decoding_size) return -1;
+	return decoding[(int)value_in];
+}
+
+void base64_init_decodestate(base64_decodestate* state_in)
+{
+	state_in->step = step_a;
+	state_in->plainchar = 0;
+}
+
+int base64_decode_block(const char* code_in, const int length_in, char* plaintext_out, base64_decodestate* state_in)
+{
+	const char* codechar = code_in;
+	char* plainchar = plaintext_out;
+	char fragment;
+	
+	*plainchar = state_in->plainchar;
+	
+	switch (state_in->step)
+	{
+		while (1)
+		{
+	case step_a:
+			do {
+				if (codechar == code_in+length_in)
+				{
+					state_in->step = step_a;
+					state_in->plainchar = *plainchar;
+					return plainchar - plaintext_out;
+				}
+				fragment = (char)base64_decode_value(*codechar++);
+			} while (fragment < 0);
+			*plainchar    = (fragment & 0x03f) << 2;
+	case step_b:
+			do {
+				if (codechar == code_in+length_in)
+				{
+					state_in->step = step_b;
+					state_in->plainchar = *plainchar;
+					return plainchar - plaintext_out;
+				}
+				fragment = (char)base64_decode_value(*codechar++);
+			} while (fragment < 0);
+			*plainchar++ |= (fragment & 0x030) >> 4;
+			*plainchar    = (fragment & 0x00f) << 4;
+	case step_c:
+			do {
+				if (codechar == code_in+length_in)
+				{
+					state_in->step = step_c;
+					state_in->plainchar = *plainchar;
+					return plainchar - plaintext_out;
+				}
+				fragment = (char)base64_decode_value(*codechar++);
+			} while (fragment < 0);
+			*plainchar++ |= (fragment & 0x03c) >> 2;
+			*plainchar    = (fragment & 0x003) << 6;
+	case step_d:
+			do {
+				if (codechar == code_in+length_in)
+				{
+					state_in->step = step_d;
+					state_in->plainchar = *plainchar;
+					return plainchar - plaintext_out;
+				}
+				fragment = (char)base64_decode_value(*codechar++);
+			} while (fragment < 0);
+			*plainchar++   |= (fragment & 0x03f);
+		}
+	}
+	/* control should not reach here */
+	return plainchar - plaintext_out;
+}
+
diff --git a/utilities/xmlrpcpp/libb64/src/cencode.c b/utilities/xmlrpcpp/libb64/src/cencode.c
new file mode 100644
index 0000000..03ba5b6
--- /dev/null
+++ b/utilities/xmlrpcpp/libb64/src/cencode.c
@@ -0,0 +1,109 @@
+/*
+cencoder.c - c source to a base64 encoding algorithm implementation
+
+This is part of the libb64 project, and has been placed in the public domain.
+For details, see http://sourceforge.net/projects/libb64
+*/
+
+#include <b64/cencode.h>
+
+const int CHARS_PER_LINE = 72;
+
+void base64_init_encodestate(base64_encodestate* state_in)
+{
+	state_in->step = step_A;
+	state_in->result = 0;
+	state_in->stepcount = 0;
+}
+
+char base64_encode_value(char value_in)
+{
+	static const char* encoding = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+	if (value_in > 63) return '=';
+	return encoding[(int)value_in];
+}
+
+int base64_encode_block(const char* plaintext_in, int length_in, char* code_out, base64_encodestate* state_in)
+{
+	const char* plainchar = plaintext_in;
+	const char* const plaintextend = plaintext_in + length_in;
+	char* codechar = code_out;
+	char result;
+	char fragment;
+	
+	result = state_in->result;
+	
+	switch (state_in->step)
+	{
+		while (1)
+		{
+	case step_A:
+			if (plainchar == plaintextend)
+			{
+				state_in->result = result;
+				state_in->step = step_A;
+				return codechar - code_out;
+			}
+			fragment = *plainchar++;
+			result = (fragment & 0x0fc) >> 2;
+			*codechar++ = base64_encode_value(result);
+			result = (fragment & 0x003) << 4;
+	case step_B:
+			if (plainchar == plaintextend)
+			{
+				state_in->result = result;
+				state_in->step = step_B;
+				return codechar - code_out;
+			}
+			fragment = *plainchar++;
+			result |= (fragment & 0x0f0) >> 4;
+			*codechar++ = base64_encode_value(result);
+			result = (fragment & 0x00f) << 2;
+	case step_C:
+			if (plainchar == plaintextend)
+			{
+				state_in->result = result;
+				state_in->step = step_C;
+				return codechar - code_out;
+			}
+			fragment = *plainchar++;
+			result |= (fragment & 0x0c0) >> 6;
+			*codechar++ = base64_encode_value(result);
+			result  = (fragment & 0x03f) >> 0;
+			*codechar++ = base64_encode_value(result);
+			
+			++(state_in->stepcount);
+			if (state_in->stepcount == CHARS_PER_LINE/4)
+			{
+				*codechar++ = '\n';
+				state_in->stepcount = 0;
+			}
+		}
+	}
+	/* control should not reach here */
+	return codechar - code_out;
+}
+
+int base64_encode_blockend(char* code_out, base64_encodestate* state_in)
+{
+	char* codechar = code_out;
+	
+	switch (state_in->step)
+	{
+	case step_B:
+		*codechar++ = base64_encode_value(state_in->result);
+		*codechar++ = '=';
+		*codechar++ = '=';
+		break;
+	case step_C:
+		*codechar++ = base64_encode_value(state_in->result);
+		*codechar++ = '=';
+		break;
+	case step_A:
+		break;
+	}
+	*codechar++ = '\n';
+	
+	return codechar - code_out;
+}
+
diff --git a/utilities/xmlrpcpp/package.xml b/utilities/xmlrpcpp/package.xml
index b7c3956..9dadba8 100644
--- a/utilities/xmlrpcpp/package.xml
+++ b/utilities/xmlrpcpp/package.xml
@@ -1,6 +1,6 @@
 <package>
   <name>xmlrpcpp</name>
-  <version>1.12.6</version>
+  <version>1.13.1</version>
   <description>
     XmlRpc++ is a C++ implementation of the XML-RPC protocol. This version is
     heavily modified from the package available on SourceForge in order to
diff --git a/utilities/xmlrpcpp/src/XmlRpcClient.cpp b/utilities/xmlrpcpp/src/XmlRpcClient.cpp
index 31cda22..b533059 100644
--- a/utilities/xmlrpcpp/src/XmlRpcClient.cpp
+++ b/utilities/xmlrpcpp/src/XmlRpcClient.cpp
@@ -1,8 +1,8 @@
 
-#include "XmlRpcClient.h"
+#include "xmlrpcpp/XmlRpcClient.h"
 
-#include "XmlRpcSocket.h"
-#include "XmlRpc.h"
+#include "xmlrpcpp/XmlRpcSocket.h"
+#include "xmlrpcpp/XmlRpc.h"
 
 #include <stdio.h>
 #include <stdlib.h>
diff --git a/utilities/xmlrpcpp/src/XmlRpcDispatch.cpp b/utilities/xmlrpcpp/src/XmlRpcDispatch.cpp
index 1d47836..e92dc5c 100644
--- a/utilities/xmlrpcpp/src/XmlRpcDispatch.cpp
+++ b/utilities/xmlrpcpp/src/XmlRpcDispatch.cpp
@@ -1,7 +1,7 @@
 
-#include "XmlRpcDispatch.h"
-#include "XmlRpcSource.h"
-#include "XmlRpcUtil.h"
+#include "xmlrpcpp/XmlRpcDispatch.h"
+#include "xmlrpcpp/XmlRpcSource.h"
+#include "xmlrpcpp/XmlRpcUtil.h"
 
 #include <math.h>
 #include <errno.h>
diff --git a/utilities/xmlrpcpp/src/XmlRpcServer.cpp b/utilities/xmlrpcpp/src/XmlRpcServer.cpp
index 013c6ec..2515142 100644
--- a/utilities/xmlrpcpp/src/XmlRpcServer.cpp
+++ b/utilities/xmlrpcpp/src/XmlRpcServer.cpp
@@ -2,12 +2,12 @@
 // added features: server can be opened on port 0 and you can read back
 // what port the OS gave you
 
-#include "XmlRpcServer.h"
-#include "XmlRpcServerConnection.h"
-#include "XmlRpcServerMethod.h"
-#include "XmlRpcSocket.h"
-#include "XmlRpcUtil.h"
-#include "XmlRpcException.h"
+#include "xmlrpcpp/XmlRpcServer.h"
+#include "xmlrpcpp/XmlRpcServerConnection.h"
+#include "xmlrpcpp/XmlRpcServerMethod.h"
+#include "xmlrpcpp/XmlRpcSocket.h"
+#include "xmlrpcpp/XmlRpcUtil.h"
+#include "xmlrpcpp/XmlRpcException.h"
 
 
 using namespace XmlRpc;
diff --git a/utilities/xmlrpcpp/src/XmlRpcServerConnection.cpp b/utilities/xmlrpcpp/src/XmlRpcServerConnection.cpp
index 76b2737..26c997f 100644
--- a/utilities/xmlrpcpp/src/XmlRpcServerConnection.cpp
+++ b/utilities/xmlrpcpp/src/XmlRpcServerConnection.cpp
@@ -1,8 +1,8 @@
 
-#include "XmlRpcServerConnection.h"
+#include "xmlrpcpp/XmlRpcServerConnection.h"
 
-#include "XmlRpcSocket.h"
-#include "XmlRpc.h"
+#include "xmlrpcpp/XmlRpcSocket.h"
+#include "xmlrpcpp/XmlRpc.h"
 #ifndef MAKEDEPEND
 # include <stdio.h>
 # include <stdlib.h>
diff --git a/utilities/xmlrpcpp/src/XmlRpcServerMethod.cpp b/utilities/xmlrpcpp/src/XmlRpcServerMethod.cpp
index 1616ff4..f40447c 100644
--- a/utilities/xmlrpcpp/src/XmlRpcServerMethod.cpp
+++ b/utilities/xmlrpcpp/src/XmlRpcServerMethod.cpp
@@ -1,6 +1,6 @@
 
-#include "XmlRpcServerMethod.h"
-#include "XmlRpcServer.h"
+#include "xmlrpcpp/XmlRpcServerMethod.h"
+#include "xmlrpcpp/XmlRpcServer.h"
 
 namespace XmlRpc {
 
diff --git a/utilities/xmlrpcpp/src/XmlRpcSocket.cpp b/utilities/xmlrpcpp/src/XmlRpcSocket.cpp
index b3c694b..8173fc9 100644
--- a/utilities/xmlrpcpp/src/XmlRpcSocket.cpp
+++ b/utilities/xmlrpcpp/src/XmlRpcSocket.cpp
@@ -2,8 +2,8 @@
 // added features: server can be opened on port 0 and you can read back
 // what port the OS gave you
 
-#include "XmlRpcSocket.h"
-#include "XmlRpcUtil.h"
+#include "xmlrpcpp/XmlRpcSocket.h"
+#include "xmlrpcpp/XmlRpcUtil.h"
 
 #ifndef MAKEDEPEND
 
diff --git a/utilities/xmlrpcpp/src/XmlRpcSource.cpp b/utilities/xmlrpcpp/src/XmlRpcSource.cpp
index 99203b0..4b44625 100644
--- a/utilities/xmlrpcpp/src/XmlRpcSource.cpp
+++ b/utilities/xmlrpcpp/src/XmlRpcSource.cpp
@@ -1,7 +1,7 @@
 
-#include "XmlRpcSource.h"
-#include "XmlRpcSocket.h"
-#include "XmlRpcUtil.h"
+#include "xmlrpcpp/XmlRpcSource.h"
+#include "xmlrpcpp/XmlRpcSocket.h"
+#include "xmlrpcpp/XmlRpcUtil.h"
 
 namespace XmlRpc {
 
diff --git a/utilities/xmlrpcpp/src/XmlRpcUtil.cpp b/utilities/xmlrpcpp/src/XmlRpcUtil.cpp
index 26f14b2..901ebc8 100644
--- a/utilities/xmlrpcpp/src/XmlRpcUtil.cpp
+++ b/utilities/xmlrpcpp/src/XmlRpcUtil.cpp
@@ -1,5 +1,5 @@
 
-#include "XmlRpcUtil.h"
+#include "xmlrpcpp/XmlRpcUtil.h"
 
 #ifndef MAKEDEPEND
 # include <ctype.h>
@@ -9,7 +9,7 @@
 # include <string.h>
 #endif
 
-#include "XmlRpc.h"
+#include "xmlrpcpp/XmlRpc.h"
 
 using namespace XmlRpc;
 
diff --git a/utilities/xmlrpcpp/src/XmlRpcValue.cpp b/utilities/xmlrpcpp/src/XmlRpcValue.cpp
index e765cfa..a7c3b0b 100644
--- a/utilities/xmlrpcpp/src/XmlRpcValue.cpp
+++ b/utilities/xmlrpcpp/src/XmlRpcValue.cpp
@@ -1,8 +1,10 @@
 
-#include "XmlRpcValue.h"
-#include "XmlRpcException.h"
-#include "XmlRpcUtil.h"
-#include "base64.h"
+#include "xmlrpcpp/XmlRpcValue.h"
+#include "xmlrpcpp/XmlRpcException.h"
+#include "xmlrpcpp/XmlRpcUtil.h"
+
+#include <b64/encode.h>
+#include <b64/decode.h>
 
 #ifndef MAKEDEPEND
 # include <iostream>
@@ -438,6 +440,29 @@ namespace XmlRpc {
     return xml;
   }
 
+  namespace {
+    std::size_t base64EncodedSize(std::size_t raw_size)
+    {
+      // encoder will still write to output buffer for empty input.
+      if (raw_size == 0) return 1;
+
+      // 4 encoded character per 3 input bytes, rounded up,
+      // plus a newline character per 72 output characters, rounded up.
+      std::size_t encoded = (raw_size + 2) / 3 * 4;
+      encoded += (encoded + 71) / 72;
+      return encoded;
+    }
+
+    std::size_t base64DecodedSize(std::size_t encoded_size)
+    {
+      // decoded will still write to output buffer for empty input.
+      if (encoded_size == 0) return 1;
+
+      // 3 decoded bytes per 4 encoded characters, rounded up just to be sure.
+      return (encoded_size + 3) / 4 * 3;
+    }
+
+  }
 
   // Base64
   bool XmlRpcValue::binaryFromXml(std::string const& valueXml, int* offset)
@@ -446,35 +471,37 @@ namespace XmlRpc {
     if (valueEnd == std::string::npos)
       return false;     // No end tag;
 
+    std::size_t encoded_size = valueEnd - *offset;
+
+
     _type = TypeBase64;
-    std::string asString = valueXml.substr(*offset, valueEnd-*offset);
-    _value.asBinary = new BinaryData();
-    // check whether base64 encodings can contain chars xml encodes...
+    // might reserve too much, we'll shrink later
+    _value.asBinary = new BinaryData(base64DecodedSize(encoded_size), '\0');
 
-    // convert from base64 to binary
-    int iostatus = 0;
-	  base64<char> decoder;
-    std::back_insert_iterator<BinaryData> ins = std::back_inserter(*(_value.asBinary));
-		decoder.get(asString.begin(), asString.end(), ins, iostatus);
+    std::stringstream buffer;
+    base64::decoder decoder;
+    std::size_t size = decoder.decode(&valueXml[*offset], encoded_size, &(*_value.asBinary)[0]);
+    _value.asBinary->resize(size);
 
-    *offset += int(asString.length());
+    *offset += encoded_size;
     return true;
   }
 
-
   std::string XmlRpcValue::binaryToXml() const
   {
-    // convert to base64
-    std::vector<char> base64data;
-    int iostatus = 0;
-	  base64<char> encoder;
-    std::back_insert_iterator<std::vector<char> > ins = std::back_inserter(base64data);
-		encoder.put(_value.asBinary->begin(), _value.asBinary->end(), ins, iostatus, base64<>::crlf());
-
     // Wrap with xml
     std::string xml = VALUE_TAG;
     xml += BASE64_TAG;
-    xml.append(base64data.begin(), base64data.end());
+
+    std::size_t offset = xml.size();
+    // might reserve too much, we'll shrink later
+    xml.resize(xml.size() + base64EncodedSize(_value.asBinary->size()));
+
+    base64::encoder encoder;
+    offset += encoder.encode(&(*_value.asBinary)[0], _value.asBinary->size(), &xml[offset]);
+    offset += encoder.encode_end(&xml[offset]);
+    xml.resize(offset);
+
     xml += BASE64_ETAG;
     xml += VALUE_ETAG;
     return xml;
@@ -586,10 +613,10 @@ namespace XmlRpc {
         }
       case TypeBase64:
         {
-          int iostatus = 0;
-          std::ostreambuf_iterator<char> out(os);
-          base64<char> encoder;
-          encoder.put(_value.asBinary->begin(), _value.asBinary->end(), out, iostatus, base64<>::crlf());
+          std::stringstream buffer;
+          buffer.write(&(*_value.asBinary)[0], _value.asBinary->size());
+          base64::encoder encoder;
+          encoder.encode(buffer, os);
           break;
         }
       case TypeArray:
diff --git a/utilities/xmlrpcpp/test/.cvsignore b/utilities/xmlrpcpp/standalone-tests/.cvsignore
similarity index 100%
rename from utilities/xmlrpcpp/test/.cvsignore
rename to utilities/xmlrpcpp/standalone-tests/.cvsignore
diff --git a/utilities/xmlrpcpp/test/FileClient.cpp b/utilities/xmlrpcpp/standalone-tests/FileClient.cpp
similarity index 95%
rename from utilities/xmlrpcpp/test/FileClient.cpp
rename to utilities/xmlrpcpp/standalone-tests/FileClient.cpp
index 81d9f3e..8cf5f12 100644
--- a/utilities/xmlrpcpp/test/FileClient.cpp
+++ b/utilities/xmlrpcpp/standalone-tests/FileClient.cpp
@@ -3,7 +3,7 @@
 // 
 // Link against xmlrpc lib and whatever socket libs your system needs (ws2_32.lib on windows)
 
-#include "XmlRpc.h"
+#include "xmlrpcpp/XmlRpc.h"
 #include <iostream>
 #include <fstream>
 #include <stdlib.h>
diff --git a/utilities/xmlrpcpp/test/FileClient.dsp b/utilities/xmlrpcpp/standalone-tests/FileClient.dsp
similarity index 100%
rename from utilities/xmlrpcpp/test/FileClient.dsp
rename to utilities/xmlrpcpp/standalone-tests/FileClient.dsp
diff --git a/utilities/xmlrpcpp/test/FileClient.vcproj b/utilities/xmlrpcpp/standalone-tests/FileClient.vcproj
similarity index 100%
rename from utilities/xmlrpcpp/test/FileClient.vcproj
rename to utilities/xmlrpcpp/standalone-tests/FileClient.vcproj
diff --git a/utilities/xmlrpcpp/test/HelloClient.cpp b/utilities/xmlrpcpp/standalone-tests/HelloClient.cpp
similarity index 98%
rename from utilities/xmlrpcpp/test/HelloClient.cpp
rename to utilities/xmlrpcpp/standalone-tests/HelloClient.cpp
index 576f63c..bcbf9fe 100644
--- a/utilities/xmlrpcpp/test/HelloClient.cpp
+++ b/utilities/xmlrpcpp/standalone-tests/HelloClient.cpp
@@ -1,7 +1,7 @@
 // HelloClient.cpp : A simple xmlrpc client. Usage: HelloClient serverHost serverPort
 // Link against xmlrpc lib and whatever socket libs your system needs (ws2_32.lib 
 // on windows)
-#include "XmlRpc.h"
+#include "xmlrpcpp/XmlRpc.h"
 #include <iostream>
 using namespace XmlRpc;
 
diff --git a/utilities/xmlrpcpp/test/HelloClient.dsp b/utilities/xmlrpcpp/standalone-tests/HelloClient.dsp
similarity index 100%
rename from utilities/xmlrpcpp/test/HelloClient.dsp
rename to utilities/xmlrpcpp/standalone-tests/HelloClient.dsp
diff --git a/utilities/xmlrpcpp/test/HelloClient.vcproj b/utilities/xmlrpcpp/standalone-tests/HelloClient.vcproj
similarity index 100%
rename from utilities/xmlrpcpp/test/HelloClient.vcproj
rename to utilities/xmlrpcpp/standalone-tests/HelloClient.vcproj
diff --git a/utilities/xmlrpcpp/test/HelloServer.cpp b/utilities/xmlrpcpp/standalone-tests/HelloServer.cpp
similarity index 98%
rename from utilities/xmlrpcpp/test/HelloServer.cpp
rename to utilities/xmlrpcpp/standalone-tests/HelloServer.cpp
index ff81ad8..2a03c6f 100644
--- a/utilities/xmlrpcpp/test/HelloServer.cpp
+++ b/utilities/xmlrpcpp/standalone-tests/HelloServer.cpp
@@ -1,6 +1,6 @@
 // HelloServer.cpp : Simple XMLRPC server example. Usage: HelloServer serverPort
 //
-#include "XmlRpc.h"
+#include "xmlrpcpp/XmlRpc.h"
 
 #include <iostream>
 #include <stdlib.h>
diff --git a/utilities/xmlrpcpp/test/HelloServer.dsp b/utilities/xmlrpcpp/standalone-tests/HelloServer.dsp
similarity index 100%
rename from utilities/xmlrpcpp/test/HelloServer.dsp
rename to utilities/xmlrpcpp/standalone-tests/HelloServer.dsp
diff --git a/utilities/xmlrpcpp/test/HelloServer.vcproj b/utilities/xmlrpcpp/standalone-tests/HelloServer.vcproj
similarity index 100%
rename from utilities/xmlrpcpp/test/HelloServer.vcproj
rename to utilities/xmlrpcpp/standalone-tests/HelloServer.vcproj
diff --git a/utilities/xmlrpcpp/test/Makefile b/utilities/xmlrpcpp/standalone-tests/Makefile
similarity index 100%
rename from utilities/xmlrpcpp/test/Makefile
rename to utilities/xmlrpcpp/standalone-tests/Makefile
diff --git a/utilities/xmlrpcpp/test/TestBase64Client.cpp b/utilities/xmlrpcpp/standalone-tests/TestBase64Client.cpp
similarity index 94%
rename from utilities/xmlrpcpp/test/TestBase64Client.cpp
rename to utilities/xmlrpcpp/standalone-tests/TestBase64Client.cpp
index de95438..479f532 100644
--- a/utilities/xmlrpcpp/test/TestBase64Client.cpp
+++ b/utilities/xmlrpcpp/standalone-tests/TestBase64Client.cpp
@@ -5,7 +5,7 @@
 // Requests a png file from the specified server and saves it in outputfile.
 // Link against xmlrpc lib and whatever socket libs your system needs (ws2_32.lib on windows)
 
-#include "XmlRpc.h"
+#include "xmlrpcpp/XmlRpc.h"
 #include <iostream>
 #include <fstream>
 #include <stdlib.h>
diff --git a/utilities/xmlrpcpp/test/TestBase64Client.dsp b/utilities/xmlrpcpp/standalone-tests/TestBase64Client.dsp
similarity index 100%
rename from utilities/xmlrpcpp/test/TestBase64Client.dsp
rename to utilities/xmlrpcpp/standalone-tests/TestBase64Client.dsp
diff --git a/utilities/xmlrpcpp/test/TestBase64Client.vcproj b/utilities/xmlrpcpp/standalone-tests/TestBase64Client.vcproj
similarity index 100%
rename from utilities/xmlrpcpp/test/TestBase64Client.vcproj
rename to utilities/xmlrpcpp/standalone-tests/TestBase64Client.vcproj
diff --git a/utilities/xmlrpcpp/test/TestBase64Server.cpp b/utilities/xmlrpcpp/standalone-tests/TestBase64Server.cpp
similarity index 93%
rename from utilities/xmlrpcpp/test/TestBase64Server.cpp
rename to utilities/xmlrpcpp/standalone-tests/TestBase64Server.cpp
index 7cb4a63..7bd47c9 100644
--- a/utilities/xmlrpcpp/test/TestBase64Server.cpp
+++ b/utilities/xmlrpcpp/standalone-tests/TestBase64Server.cpp
@@ -11,7 +11,7 @@
 #include <stdlib.h>
 
 
-#include "XmlRpc.h"
+#include "xmlrpcpp/XmlRpc.h"
 using namespace XmlRpc;
 
 
diff --git a/utilities/xmlrpcpp/test/TestBase64Server.dsp b/utilities/xmlrpcpp/standalone-tests/TestBase64Server.dsp
similarity index 100%
rename from utilities/xmlrpcpp/test/TestBase64Server.dsp
rename to utilities/xmlrpcpp/standalone-tests/TestBase64Server.dsp
diff --git a/utilities/xmlrpcpp/test/TestBase64Server.vcproj b/utilities/xmlrpcpp/standalone-tests/TestBase64Server.vcproj
similarity index 100%
rename from utilities/xmlrpcpp/test/TestBase64Server.vcproj
rename to utilities/xmlrpcpp/standalone-tests/TestBase64Server.vcproj
diff --git a/utilities/xmlrpcpp/test/TestValues.cpp b/utilities/xmlrpcpp/standalone-tests/TestValues.cpp
similarity index 94%
rename from utilities/xmlrpcpp/test/TestValues.cpp
rename to utilities/xmlrpcpp/standalone-tests/TestValues.cpp
index e770e51..4df6c70 100644
--- a/utilities/xmlrpcpp/test/TestValues.cpp
+++ b/utilities/xmlrpcpp/standalone-tests/TestValues.cpp
@@ -2,7 +2,7 @@
 
 #include <stdlib.h>
 
-#include "XmlRpcValue.h"
+#include "xmlrpcpp/XmlRpcValue.h"
 
 
 #include <assert.h>
diff --git a/utilities/xmlrpcpp/test/TestValues.dsp b/utilities/xmlrpcpp/standalone-tests/TestValues.dsp
similarity index 100%
rename from utilities/xmlrpcpp/test/TestValues.dsp
rename to utilities/xmlrpcpp/standalone-tests/TestValues.dsp
diff --git a/utilities/xmlrpcpp/test/TestValues.vcproj b/utilities/xmlrpcpp/standalone-tests/TestValues.vcproj
similarity index 100%
rename from utilities/xmlrpcpp/test/TestValues.vcproj
rename to utilities/xmlrpcpp/standalone-tests/TestValues.vcproj
diff --git a/utilities/xmlrpcpp/test/TestValuesWin32.cpp b/utilities/xmlrpcpp/standalone-tests/TestValuesWin32.cpp
similarity index 94%
rename from utilities/xmlrpcpp/test/TestValuesWin32.cpp
rename to utilities/xmlrpcpp/standalone-tests/TestValuesWin32.cpp
index f4cdafd..950f3bf 100644
--- a/utilities/xmlrpcpp/test/TestValuesWin32.cpp
+++ b/utilities/xmlrpcpp/standalone-tests/TestValuesWin32.cpp
@@ -4,7 +4,7 @@
 #include <stdlib.h>
 #include <crtdbg.h>
 
-#include "XmlRpcValue.h"
+#include "xmlrpcpp/XmlRpcValue.h"
 
 
 #include <assert.h>
diff --git a/utilities/xmlrpcpp/test/TestXml.cpp b/utilities/xmlrpcpp/standalone-tests/TestXml.cpp
similarity index 93%
rename from utilities/xmlrpcpp/test/TestXml.cpp
rename to utilities/xmlrpcpp/standalone-tests/TestXml.cpp
index 4fa707d..37218ef 100644
--- a/utilities/xmlrpcpp/test/TestXml.cpp
+++ b/utilities/xmlrpcpp/standalone-tests/TestXml.cpp
@@ -11,7 +11,7 @@
 #include <assert.h>
 #include <stdlib.h>
 
-#include "XmlRpcUtil.h"
+#include "xmlrpcpp/XmlRpcUtil.h"
 
 using namespace XmlRpc;
 
diff --git a/utilities/xmlrpcpp/test/TestXml.dsp b/utilities/xmlrpcpp/standalone-tests/TestXml.dsp
similarity index 100%
rename from utilities/xmlrpcpp/test/TestXml.dsp
rename to utilities/xmlrpcpp/standalone-tests/TestXml.dsp
diff --git a/utilities/xmlrpcpp/test/TestXml.vcproj b/utilities/xmlrpcpp/standalone-tests/TestXml.vcproj
similarity index 100%
rename from utilities/xmlrpcpp/test/TestXml.vcproj
rename to utilities/xmlrpcpp/standalone-tests/TestXml.vcproj
diff --git a/utilities/xmlrpcpp/test/Validator.cpp b/utilities/xmlrpcpp/standalone-tests/Validator.cpp
similarity index 96%
rename from utilities/xmlrpcpp/test/Validator.cpp
rename to utilities/xmlrpcpp/standalone-tests/Validator.cpp
index 2868a2d..221201d 100644
--- a/utilities/xmlrpcpp/test/Validator.cpp
+++ b/utilities/xmlrpcpp/standalone-tests/Validator.cpp
@@ -1,6 +1,6 @@
 // Validator.cpp : XMLRPC server based on the compliancy test at validator.xmlrpc.com.
 //
-#include "XmlRpc.h"
+#include "xmlrpcpp/XmlRpc.h"
 using namespace XmlRpc;
 
 #include <iostream>
diff --git a/utilities/xmlrpcpp/test/Validator.dsp b/utilities/xmlrpcpp/standalone-tests/Validator.dsp
similarity index 100%
rename from utilities/xmlrpcpp/test/Validator.dsp
rename to utilities/xmlrpcpp/standalone-tests/Validator.dsp
diff --git a/utilities/xmlrpcpp/test/Validator.vcproj b/utilities/xmlrpcpp/standalone-tests/Validator.vcproj
similarity index 100%
rename from utilities/xmlrpcpp/test/Validator.vcproj
rename to utilities/xmlrpcpp/standalone-tests/Validator.vcproj
diff --git a/utilities/xmlrpcpp/test/arrayOfStructsTest.xml b/utilities/xmlrpcpp/standalone-tests/arrayOfStructsTest.xml
similarity index 100%
rename from utilities/xmlrpcpp/test/arrayOfStructsTest.xml
rename to utilities/xmlrpcpp/standalone-tests/arrayOfStructsTest.xml
diff --git a/utilities/xmlrpcpp/test/bool_test.cpp b/utilities/xmlrpcpp/standalone-tests/bool_test.cpp
similarity index 92%
rename from utilities/xmlrpcpp/test/bool_test.cpp
rename to utilities/xmlrpcpp/standalone-tests/bool_test.cpp
index db9d414..fbec414 100644
--- a/utilities/xmlrpcpp/test/bool_test.cpp
+++ b/utilities/xmlrpcpp/standalone-tests/bool_test.cpp
@@ -1,5 +1,5 @@
 // bool_test.cpp : make sure bool variables copy around ok
-#include "XmlRpc.h"
+#include "xmlrpcpp/XmlRpc.h"
 #include <iostream>
 #include <stdlib.h>
 
diff --git a/utilities/xmlrpcpp/test/countTheEntities.xml b/utilities/xmlrpcpp/standalone-tests/countTheEntities.xml
similarity index 100%
rename from utilities/xmlrpcpp/test/countTheEntities.xml
rename to utilities/xmlrpcpp/standalone-tests/countTheEntities.xml
diff --git a/utilities/xmlrpcpp/test/easyStructTest.xml b/utilities/xmlrpcpp/standalone-tests/easyStructTest.xml
similarity index 100%
rename from utilities/xmlrpcpp/test/easyStructTest.xml
rename to utilities/xmlrpcpp/standalone-tests/easyStructTest.xml
diff --git a/utilities/xmlrpcpp/test/echo.xml b/utilities/xmlrpcpp/standalone-tests/echo.xml
similarity index 100%
rename from utilities/xmlrpcpp/test/echo.xml
rename to utilities/xmlrpcpp/standalone-tests/echo.xml
diff --git a/utilities/xmlrpcpp/test/echoStructTest.xml b/utilities/xmlrpcpp/standalone-tests/echoStructTest.xml
similarity index 100%
rename from utilities/xmlrpcpp/test/echoStructTest.xml
rename to utilities/xmlrpcpp/standalone-tests/echoStructTest.xml
diff --git a/utilities/xmlrpcpp/test/pngnow.png b/utilities/xmlrpcpp/standalone-tests/pngnow.png
similarity index 100%
rename from utilities/xmlrpcpp/test/pngnow.png
rename to utilities/xmlrpcpp/standalone-tests/pngnow.png
diff --git a/utilities/xmlrpcpp/test/port_zero_server.cpp b/utilities/xmlrpcpp/standalone-tests/port_zero_server.cpp
similarity index 98%
rename from utilities/xmlrpcpp/test/port_zero_server.cpp
rename to utilities/xmlrpcpp/standalone-tests/port_zero_server.cpp
index 0cb19d8..b60ab45 100644
--- a/utilities/xmlrpcpp/test/port_zero_server.cpp
+++ b/utilities/xmlrpcpp/standalone-tests/port_zero_server.cpp
@@ -1,6 +1,6 @@
 // HelloServer.cpp : Simple XMLRPC server example. Usage: HelloServer serverPort
 //
-#include "XmlRpc.h"
+#include "xmlrpcpp/XmlRpc.h"
 
 #include <iostream>
 #include <stdlib.h>
diff --git a/utilities/xmlrpcpp/test/CMakeLists.txt b/utilities/xmlrpcpp/test/CMakeLists.txt
new file mode 100644
index 0000000..bb3a540
--- /dev/null
+++ b/utilities/xmlrpcpp/test/CMakeLists.txt
@@ -0,0 +1,2 @@
+catkin_add_gtest(xmlrpcvalue_base64 xmlrpcvalue_base64.cpp)
+target_link_libraries(xmlrpcvalue_base64 xmlrpcpp)
diff --git a/utilities/xmlrpcpp/test/xmlrpcvalue_base64.cpp b/utilities/xmlrpcpp/test/xmlrpcvalue_base64.cpp
new file mode 100644
index 0000000..6463687
--- /dev/null
+++ b/utilities/xmlrpcpp/test/xmlrpcvalue_base64.cpp
@@ -0,0 +1,150 @@
+#include <gtest/gtest.h>
+#include "../include/xmlrpcpp/XmlRpcValue.h"
+
+#include <algorithm>
+#include <string>
+#include <sstream>
+
+int main(int argc, char **argv)
+{
+  ::testing::InitGoogleTest(&argc, argv);
+  return RUN_ALL_TESTS();
+}
+
+namespace XmlRpc
+{
+
+  XmlRpcValue base64Value(std::string const & data)
+  {
+    return XmlRpcValue(const_cast<char *>(&data[0]), data.size());
+  }
+
+  XmlRpcValue fromXml(std::string const & data)
+  {
+    int offset = 0;
+    return XmlRpcValue(data, &offset);
+  }
+
+  void removeNewlines(std::string & data)
+  {
+    data.erase(std::remove(data.begin(), data.end(), '\n'), data.end());
+  }
+
+  void assertEncodeDecode(std::string const & raw, std::string const & base64)
+  {
+    XmlRpcValue value  = base64Value(raw);
+    std::string xml    ="<value><base64>" + base64 + "</base64></value>";
+    XmlRpcValue parsed_value = fromXml(xml);
+    std::string generated_xml = value.toXml();
+    removeNewlines(generated_xml);
+
+    std::stringstream buffer;
+    value.write(buffer);
+    std::string streamed = buffer.str();
+    removeNewlines(streamed);
+    ASSERT_EQ(streamed, base64);
+
+    ASSERT_EQ(generated_xml, "<value><base64>" + base64 + "</base64></value>");
+    ASSERT_EQ(parsed_value, value);
+  }
+
+
+  TEST(xmlrpcvalue_base64, empty_string)
+  {
+    assertEncodeDecode("", "");
+  }
+
+  TEST(xmlrpcvalue_base64, hello_world)
+  {
+    assertEncodeDecode("Hello World!", "SGVsbG8gV29ybGQh");
+    assertEncodeDecode("Hello World!\n", "SGVsbG8gV29ybGQhCg==");
+  }
+
+  TEST(xmlrpcvalue_base64, random)
+  {
+    assertEncodeDecode(
+      std::string("\261", 1),
+      "sQ=="
+    );
+    assertEncodeDecode(
+      std::string("\341\370", 2),
+      "4fg="
+    );
+    assertEncodeDecode(
+      std::string("\206\262J", 3),
+      "hrJK"
+    );
+    assertEncodeDecode(
+      std::string("|5Q%", 4),
+      "fDVRJQ=="
+    );
+    assertEncodeDecode(
+      std::string("5\220,+X", 5),
+      "NZAsK1g="
+    );
+    assertEncodeDecode(
+      std::string("\247\342\007M@\270", 6),
+      "p+IHTUC4"
+    );
+    assertEncodeDecode(
+      std::string("\012\247e\013;\232*", 7),
+      "CqdlCzuaKg=="
+    );
+    assertEncodeDecode(
+      std::string("U\374\336w\351-\2503", 8),
+      "Vfzed+ktqDM="
+    );
+    assertEncodeDecode(
+      std::string("\264\204`\310\001\306\253g\026", 9),
+      "tIRgyAHGq2cW"
+    );
+    assertEncodeDecode(
+      std::string("\224\307\217\336|J^\223\237v", 10),
+      "lMeP3nxKXpOfdg=="
+    );
+    assertEncodeDecode(
+      std::string("~%\305\024\264P)\206\224\247N", 11),
+      "fiXFFLRQKYaUp04="
+    );
+    assertEncodeDecode(
+      std::string("-4\355\215Q|\367\332j\013\027\006", 12),
+      "LTTtjVF899pqCxcG"
+    );
+    assertEncodeDecode(
+      std::string("\026Q\304\204\244s%\203\023?\364\320\005", 13),
+      "FlHEhKRzJYMTP/TQBQ=="
+    );
+    assertEncodeDecode(
+      std::string("G0\306B\251\351;mwM\312i(\000", 14),
+      "RzDGQqnpO213TcppKAA="
+    );
+    assertEncodeDecode(
+      std::string("\031kpC)[t\205\026\230\343S\367\016\263", 15),
+      "GWtwQylbdIUWmONT9w6z"
+    );
+    assertEncodeDecode(
+      std::string("B&\134a\013\246u^V\001\260a\247\231}U\3278\367=G\317g\020{\277\042\373", 28),
+      "QiZcYQumdV5WAbBhp5l9Vdc49z1Hz2cQe78i+w=="
+    );
+    assertEncodeDecode(
+      std::string("[>\303\210`\270o\023FJ\004r\360\361\357\2517\345\204|\245\267P \247V\251v\025", 29),
+      "Wz7DiGC4bxNGSgRy8PHvqTflhHylt1Agp1apdhU="
+    );
+    assertEncodeDecode(
+      std::string("\264\245\360=\273E%8\023\3138\227k\222WS\227uf\314\345Y\031\365Q\024\331.\210&", 30),
+      "tKXwPbtFJTgTyziXa5JXU5d1ZszlWRn1URTZLogm"
+    );
+    assertEncodeDecode(
+      std::string("II\036\326\353\232T\221/\021\3265F}\2647A)O\2302CLY?\367O\261E\246\332\376\333\230\343\326_\373\303\225\343\351\354[\326~\264\034\305\035V\227\034\331[\012\263Y", 58),
+      "SUke1uuaVJEvEdY1Rn20N0EpT5gyQ0xZP/dPsUWm2v7bmOPWX/vDlePp7FvWfrQcxR1WlxzZWwqzWQ=="
+    );
+    assertEncodeDecode(
+      std::string("\353\317\000-\333\230\2701\251\310&J\225\347+\221q\245tb\336\225\350\323\310\327*q\261&;\2448\033X\346\277\245GM\216Oz\365\025K1\341w\230\277\272*\365\343\204\376\334E", 59),
+      "688ALduYuDGpyCZKlecrkXGldGLelejTyNcqcbEmO6Q4G1jmv6VHTY5PevUVSzHhd5i/uir144T+3EU="
+    );
+    assertEncodeDecode(
+      std::string("\235\232\352\362\304\351n\244\227\220\202hh\226\346\271\042\021d\362c\267\260\310`\000\034\247\215\350\013;#2\204(^_\333w\2233\374\337\205\253y\372\352\305F-\200v\034\331\216\205\011", 60),
+      "nZrq8sTpbqSXkIJoaJbmuSIRZPJjt7DIYAAcp43oCzsjMoQoXl/bd5Mz/N+Fq3n66sVGLX+AdhzZjoUJ"
+    );
+  }
+}

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/ros/ros-ros-comm.git



More information about the debian-science-commits mailing list