This PR finally implements the ObeliskSensor node for ZED2 cameras.
Changes
closes #54
closes #33
updated msg_conversions.h to support row-major multiarray messages while sticking to the default column-major Eigen tensor convention
fixed issues with improper configures/builds due to missing add_subdirectory calls in CMakeLists.txt files
changed dynamixel control target to be a library instead of an executable
C++ multi-camera ZED node working, publishing at proper rates confirmed
In particular, we can publish ObkImage messages without using image_transport at high rates
Confirmed that it's easy to subscribe to and view the images. For example:
import matplotlib.pyplot as plt
import rclpy
from rclpy.node import Node
from obelisk_sensor_msgs.msg import ObkImage
from obelisk_py.core.utils.msg import multiarray_to_np, np_to_multiarray
class ImageSubscriber(Node):
def __init__(self):
super().__init__('image_subscriber')
self.subscription = self.create_subscription(
ObkImage,
'/obelisk/dummy/zed2',
self.listener_callback,
10)
self.first_time = True
def listener_callback(self, msg):
self.get_logger().info('Received image data')
tensor = multiarray_to_np(msg.y)
if self.first_time:
self.first_time = False
plt.imshow(tensor[0])
plt.show()
plt.imshow(tensor[1])
plt.show()
def main(args=None):
rclpy.init(args=args)
image_subscriber = ImageSubscriber()
rclpy.spin(image_subscriber)
image_subscriber.destroy_node()
rclpy.shutdown()
if __name__ == '__main__':
main()
separated out leap and zed code in both the main lib and the ros entrypoints under a hardware subdirectory. this more easily allows for conditional builds of hardware packages based on the setup.sh script (setup also updated).
commit to convention for names of some files/targets
when writing hardware interfaces, the file should be named something like <name_of_robot>_interface.h in c++ or <name_of_robot>_interface.py in python
when naming targets in CMakeLists.txt files, we should use CamelCase and the names of the targets for libraries associated with the hardware interface headers should be named NameOfRobotInterface. The targets associated with the ROS entrypoint executables should just be called NameOfRobot. A similar convention exists for other hardware, like sensors.
however, this convention doesn't hold when naming the targets for ROS2, which should still be written in snake_case
removed sensing packages, instead replaced with more specific hardware packages
Motivation for the PR
it was discovered that the python node published very slow (about 6 Hz). however, it was determined that this wasn't because the ZED cameras could not be polled at 100Hz, but because simply publishing a raw multiarray onto some topic was extremely slow, motivating the use of ROS' image_transport libraries, which can send compressed images using syntax very similar to a publisher
this feature is only implemented in c++, so it was decided that the ZED node would be written in c++ and not python
it was discovered that in cpp, we didn't even need to use image_transport: simply publishing ObkImage message types was already very fast. to test:
Potentially some flaky behavior when running the zed nodes in a downstream project
On the night of July 30, it seemed like the cameras ran ~50Hz slower when called from a local install downstream project in obelisk examples vs in this dev container.
On July 31, with some pretty minor changes (like making mutex thinner), I found that the speed was now the same.
I've seen online now that ros2 topic hz may actually be very slow or inaccurate for high info density topics, so in obelisk_examples, I made a custom counter node in c++ to verify timings (for now, it matches the output of ros2 topic hz).
LEAP hand hardware was verified to be functional.
Future Issues
investigate/fix issues with how the Zoo target is being created - even if deps are resolved upstream, simply importing Zoo doesn't seem to fix it all. For instance, in the zed ROS2 CMakeLists.txt file, we still need to link against the zed2_sensors_node target
suppress warnings from fetched libs (yaml-cpp and zed are big offenders)
once test suite is filled out in the future, have hardware-conditional tests that aren't run in regular CI
generalize the zed2 code to all zed cameras (should not be too hard, do this when we incorporate the zed mini)
This PR finally implements the ObeliskSensor node for ZED2 cameras.
Changes
msg_conversions.h
to support row-major multiarray messages while sticking to the default column-major Eigen tensor conventionadd_subdirectory
calls inCMakeLists.txt
filesC++ multi-camera ZED node working, publishing at proper rates confirmed
ObkImage
messages without usingimage_transport
at high ratesConfirmed that it's easy to subscribe to and view the images. For example:
hardware
subdirectory. this more easily allows for conditional builds of hardware packages based on thesetup.sh
script (setup also updated).<name_of_robot>_interface.h
in c++ or<name_of_robot>_interface.py
in pythonCMakeLists.txt
files, we should useCamelCase
and the names of the targets for libraries associated with the hardware interface headers should be namedNameOfRobotInterface
. The targets associated with the ROS entrypoint executables should just be calledNameOfRobot
. A similar convention exists for other hardware, like sensors.snake_case
Motivation for the PR
image_transport
libraries, which can send compressed images using syntax very similar to a publisherimage_transport
: simply publishingObkImage
message types was already very fast. to test:Additional Commentary
ros2 topic hz
may actually be very slow or inaccurate for high info density topics, so in obelisk_examples, I made a custom counter node in c++ to verify timings (for now, it matches the output ofros2 topic hz
).Future Issues
Zoo
target is being created - even if deps are resolved upstream, simply importingZoo
doesn't seem to fix it all. For instance, in the zed ROS2 CMakeLists.txt file, we still need to link against thezed2_sensors_node
target