@@ -134,14 +134,49 @@ where
134134 payload_registry ( ) . register :: < Payload > ( ) ;
135135}
136136
137+ /// Per-channel Rx queue strategy, configured via `queue_mode` in the channel config.
138+ /// - `"fifo"` (default): ordered delivery, one sample per cycle.
139+ /// - `"ring"`: creates a buffer and drops the oldest sample when full; set `ring_size` (default 1) for buffer depth.
137140#[ derive( Debug , Clone ) ]
138- struct Ros2ChannelConfig < Id : Copy > {
141+ enum RxQueueConfig {
142+ Fifo ,
143+ Ring { size : usize } ,
144+ }
145+
146+ impl RxQueueConfig {
147+ fn from_config ( config : Option < & ComponentConfig > ) -> CuResult < Self > {
148+ let Some ( cfg) = config else {
149+ return Ok ( Self :: Fifo ) ;
150+ } ;
151+ match cfg. get :: < String > ( "queue_mode" ) ?. as_deref ( ) {
152+ Some ( "ring" ) => Ok ( Self :: Ring {
153+ size : cfg. get :: < u32 > ( "ring_size" ) ?. unwrap_or ( 1 ) as usize ,
154+ } ) ,
155+ Some ( "fifo" ) | None => Ok ( Self :: Fifo ) ,
156+ Some ( other) => Err ( CuError :: from ( format ! (
157+ "Ros2Bridge: unknown queue_mode '{other}'"
158+ ) ) ) ,
159+ }
160+ }
161+ }
162+
163+ #[ derive( Debug , Clone ) ]
164+ struct Ros2TxChannelConfig < Id : Copy > {
165+ id : Id ,
166+ route : String ,
167+ }
168+
169+ #[ derive( Debug , Clone ) ]
170+ struct Ros2RxChannelConfig < Id : Copy > {
139171 id : Id ,
140172 route : String ,
173+ queue : RxQueueConfig ,
141174}
142175
143- type Ros2Subscriber =
144- zenoh:: pubsub:: Subscriber < zenoh:: handlers:: FifoChannelHandler < zenoh:: sample:: Sample > > ;
176+ enum Ros2Subscriber {
177+ Fifo ( zenoh:: pubsub:: Subscriber < zenoh:: handlers:: FifoChannelHandler < zenoh:: sample:: Sample > > ) ,
178+ Ring ( zenoh:: pubsub:: Subscriber < zenoh:: handlers:: RingChannelHandler < zenoh:: sample:: Sample > > ) ,
179+ }
145180
146181struct Ros2TxChannel < Id : Copy > {
147182 id : Id ,
@@ -156,6 +191,7 @@ struct Ros2RxChannel<Id: Copy> {
156191 id : Id ,
157192 route : String ,
158193 entity_id : u32 ,
194+ queue : RxQueueConfig ,
159195 subscriber : Option < Ros2Subscriber > ,
160196 subscriber_token : Option < zenoh:: liveliness:: LivelinessToken > ,
161197}
@@ -183,9 +219,9 @@ where
183219 namespace : String ,
184220 node : String ,
185221 #[ reflect( ignore) ]
186- tx_channels : Vec < Ros2ChannelConfig < Tx :: Id > > ,
222+ tx_channels : Vec < Ros2TxChannelConfig < Tx :: Id > > ,
187223 #[ reflect( ignore) ]
188- rx_channels : Vec < Ros2ChannelConfig < Rx :: Id > > ,
224+ rx_channels : Vec < Ros2RxChannelConfig < Rx :: Id > > ,
189225 #[ reflect( ignore) ]
190226 ctx : Option < Ros2Context < Tx :: Id , Rx :: Id > > ,
191227}
@@ -405,8 +441,20 @@ where
405441 ) ) ?;
406442
407443 let keyexpr = topic. pubsub_keyexpr ( & node) ?;
408- let subscriber = zenoh:: Wait :: wait ( ctx. session . declare_subscriber ( keyexpr) )
409- . map_err ( cu_error_map ( "Ros2Bridge: Failed to declare subscriber" ) ) ?;
444+ let subscriber = match ctx. rx_channels [ rx_idx] . queue {
445+ RxQueueConfig :: Fifo => Ros2Subscriber :: Fifo (
446+ zenoh:: Wait :: wait ( ctx. session . declare_subscriber ( keyexpr) )
447+ . map_err ( cu_error_map ( "Ros2Bridge: Failed to declare subscriber" ) ) ?,
448+ ) ,
449+ RxQueueConfig :: Ring { size } => Ros2Subscriber :: Ring (
450+ zenoh:: Wait :: wait (
451+ ctx. session
452+ . declare_subscriber ( keyexpr)
453+ . with ( zenoh:: handlers:: RingChannel :: new ( size) ) ,
454+ )
455+ . map_err ( cu_error_map ( "Ros2Bridge: Failed to declare subscriber" ) ) ?,
456+ ) ,
457+ } ;
410458
411459 ctx. rx_channels [ rx_idx] . subscriber_token = Some ( subscriber_token) ;
412460 ctx. rx_channels [ rx_idx] . subscriber = Some ( subscriber) ;
@@ -451,7 +499,7 @@ where
451499 let mut tx_cfgs = Vec :: with_capacity ( tx_channels. len ( ) ) ;
452500 for channel in tx_channels {
453501 let route = Self :: channel_route ( channel) ?;
454- tx_cfgs. push ( Ros2ChannelConfig {
502+ tx_cfgs. push ( Ros2TxChannelConfig {
455503 id : channel. channel . id ,
456504 route,
457505 } ) ;
@@ -460,9 +508,11 @@ where
460508 let mut rx_cfgs = Vec :: with_capacity ( rx_channels. len ( ) ) ;
461509 for channel in rx_channels {
462510 let route = Self :: channel_route ( channel) ?;
463- rx_cfgs. push ( Ros2ChannelConfig {
511+ let queue = RxQueueConfig :: from_config ( channel. config . as_ref ( ) ) ?;
512+ rx_cfgs. push ( Ros2RxChannelConfig {
464513 id : channel. channel . id ,
465514 route,
515+ queue,
466516 } ) ;
467517 }
468518
@@ -510,6 +560,7 @@ where
510560 id : channel. id ,
511561 route : channel. route . clone ( ) ,
512562 entity_id : ( index + 1 ) as u32 ,
563+ queue : channel. queue . clone ( ) ,
513564 subscriber : None ,
514565 subscriber_token : None ,
515566 } )
@@ -596,15 +647,15 @@ where
596647
597648 msg. tov = Tov :: Time ( ctx. now ( ) ) ;
598649
599- let sample = {
600- let subscriber = bridge_ctx . rx_channels [ rx_idx ]
601- . subscriber
602- . as_mut ( )
603- . ok_or_else ( || CuError :: from ( "Ros2Bridge: Rx subscriber not initialized" ) ) ? ;
604- subscriber
605- . try_recv ( )
606- . map_err ( |e| CuError :: from ( format ! ( "Ros2Bridge: receive failed: {e}" ) ) ) ?
607- } ;
650+ let subscriber = bridge_ctx . rx_channels [ rx_idx ]
651+ . subscriber
652+ . as_mut ( )
653+ . ok_or_else ( || CuError :: from ( "Ros2Bridge: Rx subscriber not initialized" ) ) ? ;
654+ let sample = match subscriber {
655+ Ros2Subscriber :: Fifo ( s ) => s . try_recv ( ) ,
656+ Ros2Subscriber :: Ring ( s ) => s . try_recv ( ) ,
657+ }
658+ . map_err ( |e| CuError :: from ( format ! ( "Ros2Bridge: receive failed: {e}" ) ) ) ? ;
608659
609660 if let Some ( sample) = sample {
610661 let payload = sample. payload ( ) . to_bytes ( ) ;
@@ -633,8 +684,12 @@ where
633684
634685 for channel in rx_channels {
635686 if let Some ( subscriber) = channel. subscriber {
636- zenoh:: Wait :: wait ( subscriber. undeclare ( ) )
637- . map_err ( cu_error_map ( "Ros2Bridge: Failed to undeclare subscriber" ) ) ?;
687+ match subscriber {
688+ Ros2Subscriber :: Fifo ( s) => zenoh:: Wait :: wait ( s. undeclare ( ) )
689+ . map_err ( cu_error_map ( "Ros2Bridge: Failed to undeclare subscriber" ) ) ?,
690+ Ros2Subscriber :: Ring ( s) => zenoh:: Wait :: wait ( s. undeclare ( ) )
691+ . map_err ( cu_error_map ( "Ros2Bridge: Failed to undeclare subscriber" ) ) ?,
692+ }
638693 }
639694 }
640695
0 commit comments