Fix C++ client request wedge (uninitialized flag), depth packed as meters, and wall-clock ROS stamps - #177
Open
andrewjong wants to merge 3 commits into
Open
Conversation
Sensor and pose handlers previously stamped ROS headers with the bridge's wall clock at receive time, discarding the sim-clock time_stamp every Project AirSim message carries. That broke exact RGB/depth/pose sync downstream (ApproximateTimeSynchronizer saw network jitter) and made header stamps inconsistent with the /clock topic. Prefer the message's time_stamp (sim nanos) when present; fall back to wall clock. TF broadcasts reuse the owning message's stamp. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…queued requests TAsyncResultProviderBase's constructor initializer list skipped fis_canceled_, leaving it uninitialized heap memory. Both client worker threads consult FIsCanceled(): when the garbage read true, the sending thread silently skipped sending the request and the receiving thread popped the response entry without ever calling SetDone — so the caller's Wait() blocked forever and, with it, every later request (the ROS2 C++ bridge's clock/services wedged permanently, nondeterministically by heap state). Found via gdb thread dump against a live sim; the Python client was unaffected, which localized the fault. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ed meters The depth materials write METERS to the R channel, but the packing cast that value straight to uint16 while labeling the encoding 16UC1-mm — delivering depth quantized to 1 m steps (verified: a rig 2 m above ground read raw median 3). Convert to millimeters before the cast, and saturate at the 65535 ceiling: sky/no-hit pixels are huge or inf and the bare cast wrapped them into phantom finite depths. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
About
Three fixes found while integrating the ROS2 C++ bridge into a mapping pipeline on Linux (Blocks, UE 5.7.4):
cpp client: initialize fis_canceled_—TAsyncResultProviderBase's constructor initializer list skipsfis_canceled_, leaving it uninitialized memory. Both client worker threads consultFIsCanceled(): when the garbage reads true,RequestSendingThreadProcsilently skips sending the request andResponseReceivingThreadProcpops the pending-response entry without ever callingSetDone, so the caller'sWait()blocks forever — and every later request queues behind it. In practice this permanently wedges the C++ client's whole request channel (the ROS2 bridge's/clocknever publishes,move_*/SetPoseservice calls hang), nondeterministically depending on heap state — which is why it can appear to work on one run and deadlock on the next. One-line fix.unreal: pack depth as actual millimeters with saturation— the depth materials write meters to the R channel, butFImagePackingAsyncTaskcasts that float straight touint16while the wire encoding is declared as16UC1depth in mm. Consumers therefore receive depth quantized to whole meters (a camera 2 m above ground reads raw2). Sky / no-hit pixels (huge or inf) also wrap around in the bare cast into phantom finite depths. Fixed by converting to millimeters and saturating at 65535, which downstream can treat as "no return".ros2 cpp bridge: stamp headers/TF with sim time— every Project AirSim sensor/pose message carries the sim clock in itstime_stampfield, but the bridge stamped ROS headers with its own wall clock at receive time. That breaks time-synchronization downstream (an RGB/depth pair rendered on the same sim tick gets two different stamps, offset by network jitter) and makes header stamps inconsistent with the/clocktopic the bridge itself publishes. The bridge now prefers the message'stime_stampwhen present, falling back to wall clock; TF broadcasts reuse the owning message's stamp.How Has This Been Tested?
Linux (Ubuntu 22.04), Blocks built from this repo at current
mainwith UE 5.7.4, ROS 2 Humble; the bridge node driving a camera+non-physics robot scene and ascene_drone_sensors.jsoncscene./clocknever published and allRawRequest/SetPoseservice calls hung indefinitely (reproduced on repeated runs and two different Blocks builds); a gdb thread dump showed the rclcpp executor blocked inClient::Request → AsyncResult::Wait()with both client worker threads idle and empty queues, i.e. the entry was consumed without completion via theFIsCanceled()path. The Python client against the same sim worked, which localized the fault to the C++ client. After —/clockpublishes at a steady 50 Hz (the node's 20 ms poll),SetPoseround-trips returnsuccess=True, and a downstream RGB-D mapping pipeline ran for extended sessions with no request wedges.mono16payloads read median3for a camera ~3 m from the scene (integer meters). After — median3236(mm), and pointing the camera 45° down from 2 m altitude reads the expected ~2.8 m slant range with millimeter-scale variation; sky pixels arrive as 65535 instead of wrapped small values.message_filtersexact pairing downstream), consistent with/clock.Screenshots and videos (if appropriate):
N/A — behavioral fixes; measurable evidence described above.
🤖 Generated with Claude Code