All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
- Added the roslibrust_mcap crate which provides utilities for reading and writing MCAP files compatible ROS2 bag tools with ROS message support.
- Added the roslibrust_transforms crate which provides equivalent functionality to tf2 using the transforms crate.
- Regression in networking for ROS1 xmlrpc where an incorrect URI was being used for service registration.
- ROS1 subscribers now retry TCP connections to publishers using exponential backoff when the connection fails.
- ROS1 xmlrpc servers and TCPROS servers now much more closely follow roscpp behavior. They both explicitly listen on "0.0.0.0" instead of attempting to only listen on a specific interface. They also correctly fallback to using the IP address of the first interface in the same subnet as the ROS master if neither ROS_IP, ROS_HOSTNAME, or the system's hostname resolve to a valid IP address.
- ROS1 subscribers no longer log errors when a TCP connection fails to reply with a connection header. Some ROS tools appear to "probe" where they start a connection just to get the header.
- Reorganized some of the module structure of roslibrust_common. Users pulling things from
roslibrustwill see no change. - All API calls that were taking a topic name as "&str" now take a "impl ToGlobalTopicName" instead. This allows for more ergonomic usage of the API, and allows us to extend the API to support substitutions in the future. The API is now more strict about the format of topic names. See the documentation for GlobalTopicName for more details. Previously names like "chatter" could be handled differently be different backends that may or may not have added a leading slash automatically. Now all names MUST be a fully resolved name.
- A major optimization pass was performed on the ROS1 backend resulting in a ~79% speedup on handling a 1080p image stream. Should be very close to equal in performance to roscpp now.
- API for PublisherAny changed so that publish() takes a reference to a byte slice instead of ownership of a vector, and a publish_bytes() function was added to take ownership of a Bytes object.
- The Subscriber, Publisher, ServiceServer, and ServiceClient associated types on TopicProvider and ServiceProvider now require + Sync for their bounds. This is specifically designed to make writing async nodes easier as holding a reference to one of these types across an await point is now valid.
- ROS1 backend now exposes
subscribe_anyto allow subscribing to any topic and receiving raw bytes instead of a deserialized message.
- MockRos ServiceClients now work correctly if created before the service server is advertised.
- MockRos ServiceClients now perform a yield_now() before calling a service to help avoid race conditions in tests.
- Rosbridge backend was having serialization issues with uint8[] and char[] due to undocumented behavior of rosbridge_server using base64 encoding for uint8[] and char[] arrays. This has been fixed.
- ROS2 message hashes are now [u8; 32] instead of String and codegen will now fail if it cannot be computed instead of leaving a default value.
- roslibrust_codegen now support time conversions from chrono::DateTime and chrono::Duration to roslibrust's internal types.
- Subscribers now have a
.to_stream()method that converts them to a [futures_core::Stream] for easy integration with async Rust. See examples/tokio_stream_operations.rs for usage.
- Removed an un-used dependency on tokio from roslibrust_codegen.
- The return type of service functions has been changed from "Box<dyn std::error::Error + Send + Sync + 'static>" to
roslibrust::ServiceError. Which is an alias foranyhow::Error. This should make it easier to return errors from service functions, and deals with some tricky lifetime issues around holding ServiceServers
- Make unusual ros message definitions less likely to trip up roslibrust_codegen.
- roslibrust::ServiceProvider::ServiceServer is now Send + 'static, fixing several usage issues with holding generic service handles
- Examples and documentation for performing
asyncactions in service callbacks.
- All user provided service server functions are now executed inside of a
tokio::task::spawn_blockingcall, and blocking withing the service function is now safe.
- A new
Rostrait has been added that all backends implement. This trait behaves like a typical ROS1 node handle, and is easier to work with in generics than directly using TopicProvider or ServiceProvider.
- ZenohClient is now clone so it can implement the
Rostrait - MockRos is now clone so it can implement the
Rostrait
- roslibrust_serde_rosmsg verison updated resulting in a significant performance boost on serializing large messages. 95% gains measured on 1080p color image serialization. 25% gains measured on roundtrip image benchmarks with ros1 backend.
- roslibrust_mock now provides a basic mock implementation of roslibrust's generic traits for use in building automated testing of nodes.
- roslibrust_zenoh now proivides a Zenoh client that is compatible with the zenoh-ros1-plugin / zenoh-ros1-bridge
- roslibrust_ros1 now provides a ROS1 native client as a standalone crate
- roslibrust_rosbridge now provides a rosbridge client as a standalone crate
- roslibrust_rosapi now provides a generic interface for the rosapi node compatible with both rosbridge and ros1 backends
- Keeping a ros1::ServiceServer alive no longer keeps the underlying node alive past the last ros1::NodeHandle being dropped.
- Dropping the last ros1::NodeHandle results in the node cleaning up any advertises, subscriptions, and services with the ROS master.
- Generated code now includes various lint attributes to suppress warnings.
- TCPROS header parsing now ignores (the undocumented fields) response_type and request_type and doesn't produce warnings on them.
- ROS1 native service servers now respect the "persistent" header field, and automatically close the underlying TCP socket after a single request unless persistent is set to 1 in the connection header.
- A major reorganization of the internals of roslibrust was done to improve our ability to support multiple backends.
As part of the organization the rosbridge backend has been moved under the the
rosbridgemodule, soroslibrust::ClientHandlenow becomesroslibrust::rosbridge::ClientHandle. - Internal integral type Time changed from u32 to i32 representation to better align with ROS1
- Conversions between ROS Time and Duration to std::time::Time and std::time::Duration switched to TryFrom as they can be fallible.
- Main crate Error type has been simplified to leak fewer internal types.
- roslibrust_codegen is now intended to be accessed by users via the
codegenfeature flag on roslibrust. - roslibrust_codegen_macro is now intended to be accessed by users via the
macrofeature flag on roslibrust. - Code generated by roslibrust_codegen now depends on
roslibrustwith thecodegenfeature flag being available to it.
- ROS1 Native Publishers no longer occasionally truncate very large messages when configured with latching
- Passing of large messages containing uint8[] arrays is now substantially faster
- Generated code now relies on serde_bytes to enable faster handling of uint8[] arrays
- Switched to a fork of serde_rosmsg to enable faster handling of uint8[] arrays
- ROS1 Native Publishers now support latching behavior
- The XML RPC client for interacting directly with the rosmaster server has been exposed as a public API
- Experimental: Initial support for writing generic clients that can be compile time specialized for rosbridge or ros1
- Can subscribe to any topic and get raw bytes instead of a deserialized message of known type
- Can publish to any topic and send raw bytes instead of a deserialized message
- ROS1 Native Publishers correctly call unadvertise when dropped
- ROS1 Native Publishers no longer occasionally truncate very large messages (>5MB)
- ROS1 Node Handle's advertise() now requires a latching argument
- RosBridge ClientHandle [call_service()] is now templated on the service type instead of on both the request and response type. This is to bring it in line with the ROS1 API.
- RosBridge ClientHandle::Publisher publish() now takes a reference to the message instead of taking ownership. This is to bring it in line with the ROS1 API.
- The RosServiceType trait used by codegen now requires 'static + Send + Sync this will not affect any generated types, but custom types may have issue.
- Bug with message_definitions provided by Publisher in the connection header not being the fully expanded definition.
- Bug with ROS1 native subscribers not being able to receive messages larger than 4096 bytes.
- Bug with ros1 native publishers not parsing connection headers correctly
- ROS1 native service servers and service clients are now supported (experimental feature)
- The reconnection logic for rosbridge clients was fundamentally broken and failing to reconnect. This has been fixed.
- Generic subscriptions coming from rospy that specified "*" as the md5sum were not properly handled. This has been fixed.
- Code generated by roslibrust_codegen now depends only on libraries exposed by roslibrust_codegen. This means that crates that were previously adding dependencies on serde, serde-big-array, and smart-default will no longer need to do so.
- A significant reworking of the error types in the ROS1 native client was performed to move away from the
Box<dyn Error + Send + Sync>pattern and instead use theanyhowcrate.
- The build.rs example in example_package now correctly informs cargo of filesystem dependencies
- The
advertise_servicemethod inrosbridge/client.rsnow accepts closures - Expose additional methods useful for custom cases not using package manifests or standard ROS2 setups
- Messages containing fixed sized arrays now successfully serialize and deserialize when using ROS1 native communication
- The function interface for top level generation functions in
roslibrust_codegenhave been changed to include the list of dependent filesystem paths that should trigger re-running code generation. Note: new files added to the search paths will not be automatically detected. - [Breaking Change] Codegen now generates fixed sized arrays as arrays [T; N] instead of Vec
- Removed
find_and_generate_ros_messages_relative_to_manifest_dir!this proc_macro was changing the current working directory of the compilation job resulting in a variety of strange compilation behaviors. Build.rs scripts are recommended for use cases requiring fine grained control of message generation. - The function interface for top level generation functions in
roslibrust_codegenhave been changed to include the list of dependent filesystem paths that should trigger re-running code generation. Note: new files added to the search paths will not be automatically detected. - Refactor the
ros1::nodemodule into separate smaller pieces. This should be invisible externally (and no changes to examples were required).
- Experimental support for ROS1 native communication behind the
ros1feature flag - Generation of C++ source added via
roslibrust_genmsgalong with arbitrary languages via passed in templates - Generation of Rust source for actions
- Example for custom generic message usage with rosbridge
- Example for async native ROS1 listener
- Example for async native ROS1 publisher
- Incorrect handling of ROS1 message string constants
crawlfunction inroslibrust_codegenupdated to a more flexible API- Overhaul of error handling in roslibrust_codegen to bubble errors up, and remove use of panic! and unwrap(). Significantly better error messages should be produced from proc_macros and build.rs files. Direct usages of the API will need to be updated to handle the returned error type.
- RosMessageType trait now has associated constants for MD5SUM and DEFINITION to enable ROS1 native support. These constants are optional at this time with a default value of "" provided.
- Support for default field values in ROS2 messages
- Added public APIs for getting message data from search and for generating Rust code given message data in roslibrust_codegen
- More useful logs available when running codegen
- Refactor some of the public APIs and types in roslibrust_codegen (concept of
ParsedMessageFilevsMessageFile) - Added a method
get_md5sumtoMessageFile - Additional code generation API and macro which excludes
ROS_PACKAGE_PATH
- Bug causing single quoted string constants in message files to not be parsed correctly
- Bug causing float constants in message files to cause compiler errors because
f32 = 0;is not allowed in rust - Bug where packages were not properly de-duplicated during discovery.
advertise_serviceandsubscribemethods on ClientHandle were changed from needing&mut selfto&self
- Initial support for ROS2 message generation
- Initial integration testing for ROS2 all basic functionality covered
- CI testing for Humble
- The generated
chartype within rust is now u8. - Package names are now determined by the
nametag within package.xml instead of by directory name
- No longer generate empty
implblocks from message structs that have not associated constants - Significant improvement to documentation with expanded examples
advertise_serviceno longer panics if multiple advertise attempts made to same topic
Fix to docs.rs build.
- Service server example
Clientis nowClientHandle- All identifiers in generated code are now escaped with
r# advertise_servicenow returns aServiceHandlewhich controls the lifetime of the service
- Fixed issue where the spin and reconnect context would never drop even if there were no more
ClientHandles - Fixed parsing issue with triple dashes in comments of service files
- Fixed bug in generation where message properties or constants had names conflicting with Rust reserved keywords
Yanked version due to failed publish
Yanked version due to failed publish
- Support for service servers
- Into<> helpers for Time and Duration for tokio and std
- Failure in message generation caused by files without extensions
- Failure in message generation caused by failing to quote around string constants
- Failure in message generation caused by bad design of integral types TimeI and DurationI
Initial public release
Steps:
- Starting on master
- Edit change log
- Revise the version numbers in Cargo.toml files
- Commit the changes
- Publish all crates using
./publish_all.shwhich invokes publish in the correct order - Push to master
- Tag and push tag