splintered-reality / py_trees

Python implementation of behaviour trees.
Other
433 stars 143 forks source link

Implementation of logging as 'print' statements #419

Open gitpushoriginmaster opened 1 year ago

gitpushoriginmaster commented 1 year ago

Hi @stonier , Why are all the logs in your Logger class handled with print and not by the logging module? I see you comment at the beggining of logging.py, but still - what would you think about having the option to switch to a logging.Logger by some boolean flag?

stonier commented 1 year ago

Short answer - It just never got past the quick and easy print statement :P

We only ever used logging to print out some information in demos / tests. Wherever there was an integration, custom behaviours and visitors made use of the logging framework the trees were running in.

I wouldn't be averse to having it use the standard python logger, even by default. What's your use case?

gitpushoriginmaster commented 1 year ago

My use case is building a Python-only program (no ROS, no C++ binding) where the state is controlled by a BT instead of an FSM, and wishing to simulate recorded runs for debugging/analysis purposes. When using conditions as Behaviours, I would like to include such logs to allow reproducability, so I can later write code that runs a BT and returns a status by what happened in the logged run (maybe even with the option to simulate the Behaviour's runtime). As I see it, overriding sys.stdout with a desired log file is not a valid solution since some things need to be printed to console, other things needs to be logged, and some need both.

stonier commented 1 year ago

Ok, so there's probably three use cases in mind here. In order of complexity:

  1. Debugging and introspection - a text log would suffice for this.
  2. Replay - need to capture, at each tick, at least the a) tree composition b) tree state and b) blackboard state (remember, behaviours and subtrees can be dynamically added/pruned from the tree between ticks)
  3. Resimulate - would need to additionally capture behaviour configuration at launch and internal state at each tick

  1. Use a standard python logging framework, behaviours and composites could add some level of useful information by default, behaviour authors supply the rest. If the same logging framework can be tapped into at startup and between ticks by the application, then the application (tree) author can include addiitional information about the tree as a whole. This use case 'could' help you get to two if you force some structure on the log, but text parsing to do so is pretty expensive.

  2. The easiest way of doing this is to have some kind of data schema, run some post-tick visitors on the tree to collect the required information and also the blackboard state (or the active part of it, or just the delta on the blackboard). Then we have all the information we need to write a log or generate a stream to a visualiser (this is in fact what the ros2 tree + viewer pair do). I've been wanting to spin up a pipeline to do this for non-ros visualisation (#415). That same pipeline could be piggypacked to create replayable logs. You could also create a json like structure that behaviours could populate to add to the log (similar to the feedback_message variable in Behaviours today.

  3. This would be nice, but not possible. The internal state is not complete, since very often a behaviour is connected across the wire to another process which doesn't expose it's state. I would like to create a serialisable format for construction of trees though, at least then they could be relaunched more reproducibly. This is something of a todo though.

^TLDR; Unpacking 2 would be a great feature to have.