3grepros library interface.
7- {@link grepros.inputs.AppSource AppSource}: produces messages from iterable or pushed data
8- {@link grepros.inputs.BagSource BagSource}: produces messages from ROS bagfiles
9- {@link grepros.inputs.LiveSource LiveSource}: produces messages from live ROS topics
13- {@link grepros.outputs.AppSink AppSink}: provides messages to callback function
14- {@link grepros.outputs.BagSink BagSink}: writes messages to bagfile
15- {@link grepros.outputs.ConsoleSink ConsoleSink}: prints messages to console
16- {@link grepros.plugins.auto.csv.CsvSink CsvSink}: writes messages to CSV files, each topic to a separate file
17- {@link grepros.plugins.auto.html.HtmlSink HtmlSink}: writes messages to an HTML file
18- {@link grepros.outputs.LiveSink LiveSink}: publishes messages to ROS topics
19- {@link grepros.plugins.mcap.McapSink McapSink}: writes messages to MCAP file
20- {@link grepros.outputs.MultiSink MultiSink}: combines any number of sinks
21- {@link grepros.plugins.parquet.ParquetSink ParquetSink}: writes messages to Apache Parquet files
22- {@link grepros.plugins.auto.postgres.PostgresSink PostgresSink}: writes messages to a Postgres database
23- {@link grepros.plugins.auto.sqlite.SqliteSink SqliteSink}: writes messages to an SQLite database
24- {@link grepros.plugins.sql.SqlSink SqlSink}: writes SQL schema file for message type tables and topic views
26{@link grepros.api.BaseBag Bag}: generic bag interface.
27{@link grepros.search.Scanner Scanner}: ROS message grepper.
29Format-specific bag classes:
31- {@link grepros.ros1.ROS1Bag ROS1Bag}: ROS1 bag reader and writer in .bag format
32- {@link grepros.ros2.ROS2Bag ROS2Bag}: ROS2 bag reader and writer in .db3 SQLite format
33- {@link grepros.plugins.embag.EmbagReader EmbagReader}: ROS1 bag reader
34 using the <a href="https://github.com/embarktrucks/embag">embag</a> library
37Output sink `write_options` arguments can be given
with underscores
38instead of dashes, e.g. `
"rollover_size"` instead of `
"rollover-size"`.
40------------------------------------------------------------------------------
41This file
is part of grepros - grep
for ROS bag files
and live topics.
42Released under the BSD License.
47------------------------------------------------------------------------------
49## @namespace grepros.library
50from . plugins.auto.csv import CsvSink
51from . plugins.auto.html
import HtmlSink
52from . plugins.auto.postgres
import PostgresSink
53from . plugins.auto.sqlite
import SqliteSink
54from . plugins.mcap
import McapBag, McapSink
55from . plugins.parquet
import ParquetSink
56from . plugins.sql
import SqlSink
59from . inputs
import AppSource, BagSource, LiveSource, Source
60from . outputs
import AppSink, BagSink, ConsoleSink, LiveSink, MultiSink, Sink
61from . search
import BooleanResult, ExpressionTree, Scanner
70def grep(args=None, **kwargs):
72 Yields matching messages from specified source.
74 Initializes grepros
if not already initialized.
76 Read
from bagfiles: `
grep(file=
"2022-10-*.bag", pattern=
"cpu")`.
78 Read
from live topics: `
grep(live=
True, pattern=
"cpu")`.
81 @param args arguments
as namespace
or dictionary, case-insensitive;
82 or a single path
as the ROS bagfile to read,
85 @param kwargs any
and all arguments
as keyword overrides, case-insensitive
89 @param args.file names of ROS bagfiles to read
if not all
in directory
90 @param args.path paths to scan
if not current directory
91 @param args.recurse recurse into subdirectories when looking
for bagfiles
92 @param args.decompress decompress archived bags to file directory
93 @param args.reindex make a copy of unindexed bags
and reindex them (ROS1 only)
94 @param args.orderby
"topic" or "type" if any to group results by
95 @param args.timescale emit messages on original timeline
from first message
96 at given rate, 0 disables
97 @param args.timescale_emission start timeline
from first matched message
not first
in bag
102 @param args.live whether reading messages
from live ROS topics
103 @param args.queue_size_in subscriber queue size (default 10)
104 @param args.ros_time_in stamp messages
with ROS time instead of wall time
108 @param args.app whether reading messages
from iterable
or pushed data;
109 may contain the iterable itself
110 @param args.iterable iterable yielding (topic, msg, stamp)
or (topic, msg);
111 yielding `
None` signals end of content
113 @param args.topic ROS topics to read
if not all
114 @param args.type ROS message types to read
if not all
115 @param args.skip_topic ROS topics to skip
116 @param args.skip_type ROS message types to skip
117 @param args.start_time earliest timestamp of messages to read
118 @param args.end_time latest timestamp of messages to read
119 @param args.start_index message index within topic to start
from
120 @param args.end_index message index within topic to stop at
122 @param args.nth_message read every Nth message
in topic, starting
from first
123 @param args.nth_interval minimum time interval between messages
in topic,
124 as seconds
or ROS duration
126 @param args.select_field message fields to use
in matching
if not all
127 @param args.noselect_field message fields to skip
in matching
129 @param args.unique emit messages that are unique
in topic
130 (select_field
and noselect_field apply
if specified)
131 @param args.condition Python expressions that must evaluate
as true
132 for message to be processable, see ConditionMixin
136 @param args.pattern pattern(s) to find
in message field values
137 @param args.fixed_string pattern contains ordinary strings,
not regular expressions
138 @param args.case use case-sensitive matching
in pattern
139 @param args.invert select messages
not matching pattern
140 @param args.expression pattern(s) are a logical expression
141 like
'this AND (this2 OR NOT "skip this")',
142 with elements
as patterns to find
in message fields
144 @param args.nth_match emit every Nth match
in topic, starting
from first
145 @param args.max_count number of matched messages to emit (per file
if bag input)
146 @param args.max_per_topic number of matched messages to emit
from each topic
147 @param args.max_topics number of topics to
print matches
from
149 @param args.before number of messages of leading context to emit before match
150 @param args.after number of messages of trailing context to emit after match
151 @param args.context number of messages of leading
and trailing context
154 @param args.highlight highlight matched values
155 @param args.match_wrapper string to wrap around matched values,
156 both sides
if one value, start
and end
if more than one,
157 or no wrapping
if zero values
159 @return {
@link grepros.Scanner.GrepMessage GrepMessage} namedtuples
160 of (topic, message, timestamp, match, index)
162 DEFAULT_ARGS = dict(FILE=[], LIVE=False, APP=
False, ITERABLE=
None,
163 COLOR=
"never", HIGHLIGHT=
False)
166 is_bag = isinstance(args, Bag)
or \
167 common.is_iterable(args)
and all(isinstance(x, Bag)
for x
in args)
168 args = {
"FILE": str(args)}
if isinstance(args, common.PATH_TYPES)
else \
169 {}
if is_bag
or isinstance(args, Source)
else args
170 args = common.ArgumentUtil.validate(common.ensure_namespace(args, DEFAULT_ARGS, **kwargs))
171 if not _inited:
init(args)
173 if common.is_iterable(args.APP)
and not common.is_iterable(args.ITERABLE):
174 args.APP, args.ITERABLE =
True, args.APP
175 src = args0
if isinstance(args0, Source)
else \
179 if args
and isinstance(args0, Source): src.configure(**kwargs)
183 for x
in Scanner(args).find(src):
yield x
185 if not isinstance(args0, (Bag, Source)): src.close()
188def source(args=None, **kwargs):
192 Initializes grepros
if not already initialized.
194 @param args arguments
as namespace
or dictionary, case-insensitive;
195 or a single path
as the ROS bagfile to read
196 @param kwargs any
and all arguments
as keyword overrides, case-insensitive
197 @param args.file one
or more names of ROS bagfiles to read
from
198 @param args.live read messages
from live ROS topics instead
199 @param args.app read messages
from iterable
or pushed data instead;
200 may contain the iterable itself
204 @param args.file names of ROS bagfiles to read
if not all
in directory
205 @param args.path paths to scan
if not current directory
206 @param args.recurse recurse into subdirectories when looking
for bagfiles
207 @param args.orderby
"topic" or "type" if any to group results by
208 @param args.decompress decompress archived bags to file directory
209 @param args.reindex make a copy of unindexed bags
and reindex them (ROS1 only)
210 @param args.timescale emit messages on original timeline
from first message
211 at given rate, 0 disables
212 @param args.timescale_emission start timeline
from first matched message
not first
in bag
213 @param args.progress whether to
print progress bar
217 @param args.queue_size_in subscriber queue size (default 10)
218 @param args.ros_time_in stamp messages
with ROS time instead of wall time
219 @param args.progress whether to
print progress bar
223 @param args.iterable iterable yielding (topic, msg, stamp)
or (topic, msg);
224 yielding `
None` signals end of content
228 @param args.topic ROS topics to read
if not all
229 @param args.type ROS message types to read
if not all
230 @param args.skip_topic ROS topics to skip
231 @param args.skip_type ROS message types to skip
232 @param args.start_time earliest timestamp of messages to read
233 @param args.end_time latest timestamp of messages to read
234 @param args.start_index message index within topic to start
from
235 @param args.end_index message index within topic to stop at
236 @param args.unique emit messages that are unique
in topic
237 @param args.select_field message fields to use
for uniqueness
if not all
238 @param args.noselect_field message fields to skip
for uniqueness
239 @param args.nth_message read every Nth message
in topic, starting
from first
240 @param args.nth_interval minimum time interval between messages
in topic,
241 as seconds
or ROS duration
242 @param args.condition Python expressions that must evaluate
as true
243 for message to be processable, see ConditionMixin
245 DEFAULT_ARGS = dict(FILE=[], LIVE=False, APP=
False, ITERABLE=
None)
246 args = {
"FILE": str(args)}
if isinstance(args, common.PATH_TYPES)
else args
247 args = common.ensure_namespace(args, DEFAULT_ARGS, **kwargs)
248 if not _inited:
init(args)
250 if common.is_iterable(args.APP)
and not common.is_iterable(args.ITERABLE):
251 args.APP, args.ITERABLE =
True, args.APP
252 result = (LiveSource
if args.LIVE
else AppSource
if args.APP
else BagSource)(args)
257def sink(args=None, **kwargs):
262 Initializes grepros
if not already initialized.
264 @param args arguments
as namespace
or dictionary, case-insensitive;
265 or a single item
as sink target like bag filename
266 @param kwargs any
and all arguments
as keyword overrides, case-insensitive
267 @param args.app provide messages to given callback function
268 @param args.console
print matches to console
269 @param args.publish publish matches to live topics
270 @param args.write file
or other target like Postgres database to write,
271 as "target",
or [
"target", dict(format=
"format", ..)]
272 or [[..target1..], [..target2..], ..]
273 @param args.write_options format-specific options like
274 {
"overwrite": whether to overwrite existing file
279 @param args.line_prefix
print source prefix like bag filename on each message line
280 @param args.max_field_lines maximum number of lines to
print per field
281 @param args.start_line message line number to start output
from
282 @param args.end_line message line number to stop output at
283 @param args.max_message_lines maximum number of lines to output per message
284 @param args.lines_around_match number of message lines around matched fields to output
285 @param args.matched_fields_only output only the fields where match was found
286 @param args.wrap_width character width to wrap message YAML output at
287 @param args.match_wrapper string to wrap around matched values,
288 both sides
if one value, start
and end
if more than one,
289 or no wrapping
if zero values
293 @param args.color
False or "never" for not using colors
in replacements
294 @param args.highlight highlight matched values (default true)
295 @param args.emit_field message fields to emit
if not all
296 @param args.noemit_field message fields to skip
in output
297 @param args.max_field_lines maximum number of lines to output per field
298 @param args.start_line message line number to start output
from
299 @param args.end_line message line number to stop output at
300 @param args.max_message_lines maximum number of lines to output per message
301 @param args.lines_around_match number of message lines around matched fields to output
302 @param args.matched_fields_only output only the fields where match was found
303 @param args.wrap_width character width to wrap message YAML output at
304 @param args.match_wrapper string to wrap around matched values,
305 both sides
if one value, start
and end
if more than one,
306 or no wrapping
if zero values
310 @param args.queue_size_out publisher queue size (default 10)
311 @param args.publish_prefix output topic prefix, prepended to input topic
312 @param args.publish_suffix output topic suffix, appended to output topic
313 @param args.publish_fixname single output topic name to publish to,
314 overrides prefix
and suffix
if given
318 @param args.emit callback(topic, msg, stamp, highlighted msg, index
in topic)
320 @param args.metaemit callback(metadata dict)
if any,
321 invoked before first emit
from source batch
325 @param args.meta whether to
print metainfo
326 @param args.verbose whether to
print debug information
328 DEFAULT_ARGS = dict(CONSOLE=False, PUBLISH=
False, WRITE=[], APP=
False, EMIT=
None, METAEMIT=
None)
331 args = {
"WRITE": str(args)}
if isinstance(args, common.PATH_TYPES)
else args
332 args = common.ensure_namespace(args, DEFAULT_ARGS, **kwargs)
333 if not _inited:
init(args)
336 if isinstance(args.WRITE, common.PATH_TYPES):
337 args.WRITE = [[args.WRITE]]
338 elif isinstance(args.WRITE, (list, tuple))
and isinstance(args.WRITE[0], common.PATH_TYPES):
339 args.WRITE = [args.WRITE]
340 if callable(args.APP)
and not callable(args.EMIT): args.APP, args.EMIT =
True, args.APP
344 result = multisink.sinks[0]
if len(multisink.sinks) == 1
else multisink
348def init(args=None, **kwargs):
350 Initializes ROS version bindings, loads all built-in plugins
if dependencies available.
353 @param args.plugin one
or more extra plugins to load,
354 as full names
or instances of Python module/
class
355 @param kwargs any
and all arguments
as keyword overrides, case-insensitive
358 args = common.ensure_namespace(args, {
"PLUGIN": []}, **kwargs)
360 if args: plugins.configure(args)
363 common.ConsolePrinter.configure(color=
None, apimode=
True)
366 for x
in (plugins.mcap, plugins.parquet, plugins.sql):
367 try: plugins.configure(PLUGIN=x)
368 except Exception:
pass
369 Bag.READER_CLASSES.add(McapBag)
370 Bag.WRITER_CLASSES.add(McapBag)
371 if args.PLUGIN: plugins.configure(args)
373 api.TypeMeta.LIFETIME, api.TypeMeta.POPULATION = 0, 100
379 "AppSink",
"AppSource",
"Bag",
"BagSink",
"BagSource",
"BooleanResult",
"ConsoleSink",
380 "CsvSink",
"ExpressionTree",
"HtmlSink",
"LiveSink",
"LiveSource",
"McapBag",
"McapSink",
381 "MultiSink",
"ParquetSink",
"PostgresSink",
"Scanner",
"Sink",
"Source",
"SqliteSink",
382 "SqlSink",
"grep",
"init",
"sink",
"source",
Combines any number of sinks.
MCAP bag interface, providing most of rosbag.Bag interface.
source(args=None, **kwargs)
Convenience for creating a Source instance from arguments.
sink(args=None, **kwargs)
Convenience for creating a Sink instance from arguments, MultiSink if several outputs.
init(args=None, **kwargs)
Initializes ROS version bindings, loads all built-in plugins if dependencies available.
grep(args=None, **kwargs)
Yields matching messages from specified source.