matlab wrapping + stdstream => mexPrintf

Issue #303 closed
Simon Julier created an issue

Dear All,

I'm just starting to put my toe in the water with GTSAM (the goal is initially use it for teaching in a robotics course). One issue is that we are likely to use code written for C++ in matlab. Various bits of debugging output are generated by the various standard stream operators (cout, cerr, etc.) These do not appear in the matlab console by default. However, custom streams can be used. For example, see the bottom of:

http://stackoverflow.com/questions/243696/correctly-over-loading-a-stringbuf-to-replace-cout-in-a-matlab-mex-file

I have actually done some edits locally and it's mostly fairly easy to add to the matlab wrapper (mostly just requires modifications to Module.cpp).

Would such as capability be of interest? If so, I can create a fork and add it.

Comments (15)

  1. Frank Dellaert

    Possibly a good addition. Would love to discuss in more detail before you spend a lot of work on it.

  2. Simon Julier reporter

    Sure. The basic issue is this. MEX doesn't directly show the output of iostreams to users and we have to use special commands such as mexPrintf instead. This substitution gets very onerous if, for example, we want to print the output from somewhere inside the GTSAM C++ library (which I've been doing for debugging). The reason is that one would have to put mexPrintf, conditionals, etc., everywhere. Similar, if I were to write and link my own factors in C++, to get debugging to appear in matlab I'd have to add lots of tweaks to the code.

    The ostream forwarding constructs an object which redirects stdio directly to matlab's outputs. As a result, it's transparent to most C++ code (unless that code was doing something funny with stdio).

    There are three ways it could be done:

    1. Set up a completely separate mex file with a static instance of the redirection object. On the one hand, this completely decouples redirection from GTSAM altogether and could literally be a "mini-MEX" in its own right. However, because it's a static instance, it means the output of all MEX files is forwarded.
    2. Put a static instance of the redirection object into the GTSAM wrapper. This means that forwarding would happen as long as GTSAM is loaded.
    3. Put a forward call in each individual method. This means that GTSAM only will echo its output. However, this would add some performance overhead. Also, I don't quite know what happens if we have the chain of MEX => calls matlab => calls MEX.

    Thoughts?

    Cheers,

    Simon

  3. Frank Dellaert

    Some friendly push-back, after thinking about this: when creating new factors, I mostly have done so driven by unit tests in C++ (test first, then write, then test again). Sometimes some debugging code is useful there, although a well written set of tests typically pre-empts this. All printing is C++ only and is removed from the code before checkin.

    Then, if I use these factors in MATLAB, because printing is slow anyway, I query factors in MATLAB (using wrapped methods) and print in MATLAB. Writing printing code in C++ and re-compiling is slow and almost defeats the purpose of working in MATLAB.

    Hence, do we really care about inserting code in C++ and seeing the result in MATLAB? Devil's advocate position: no.

  4. Simon Julier reporter

    Well, three reasons are below. Arguably the second and third are just debug options which might not be needed once the code is debugged. The first provides output which I think would be useful all of the time.

    1. Existing diagnostic output: The existing C++ code prints stuff out via std::cout / std::cerr responses which are not part of any print(.) routine which could be sent to a stream. Examples include LevenbergMarquardtOptimizer (with verbosity levels set high) InitializePose3 (reporting that the graph didn't build properly) and SubgraphBuilder (reporting an undefined skeleton type). Without providing some kind of streaming support, none of those messages would be shown to a matlab user.
    2. Debugging: When I've been trying to track down some issues with the wrapper, it's useful to instrument some of the C++ code directly to see what's going on. This includes stuff that appears to "work" outside of Matlab but fails to do so internally, sometimes because of subtle memory management issues.
    3. Understanding the code: Related to 2., printing inside the C++ code makes it easier to understand what's going on.
  5. Frank Dellaert

    OK, #1 is a valid concern. So, the redirection is automatic, without any changes in the GTSAm code? That would be pretty interesting (your option 2, I think), esp. if it can be controlled via a make flag. What do you think?

  6. Simon Julier reporter

    That's right. I actually have a (slightly nasty) implementation which does option 2 already and is controlled by a flag.

    I'll create a branch feature/matlab_iostream_redirection and check the code in now.

    Warning - my experiences with git tend to be somewhat chaotic, so hopefully nothing bad will happen!

  7. Simon Julier reporter

    Well, that's embarassing. I was just checking over some stuff in detail and found that option 3 already appears to be implemented in the gtsam wrapper (see mstream in matlab.h, and mexPrintf in the generated wrapper).

    Not sure why I didn't see it before.

    Assuming you are happy with the mechanism as it stands, this issue can be closed. Sorry for wasting time.

  8. Frank Dellaert

    Interesting. I think maybe @richardroberts implemented this - I don't remember it. No time wasted, it just means it is not very well documented - which is a bug, too. Now that you know this, how would you use it and where would you expect to find this documented?

  9. Simon Julier reporter

    Cool. The use cases would be as above - namely to present necessary feedback from the C++ portions of GTSAM to matlab.

    I guess the place to put it would be in the README for matlab (but does anybody actually read README files?)

    https://research.cc.gatech.edu/borg/sites/edu.borg/files/downloads/README-gtsam-toolbox.txt

    The other idea would be to work it into one of the examples. e.g., to switch the verboseness level to show what's actually going on during an iteration. I'll have a look at how to do this as part of my general learning practice with GTSAM.

  10. Simon Julier reporter

    Oh... Additional request. Would it be possible to add as a reminder the need to set GTSAM_INSTALL_MATLAB_TOOLBOX in the README file as well? One of the students here spent several hours trying to figure out why the instructions in README-gtsam-toolbox.txt didn't seem to work.

  11. Frank Dellaert

    Feel free to modify the README file with this and the comments about the streaming in a branch, and create a PR.

  12. Simon Julier reporter

    Since the comment about the matlab stream is related to the discussion this thread, I've pushed the update to the branch feature/matlab_iostream_redirection. There should be just one change to the README file. This file also briefly mentions the use of the wrap tool and automatic generation of the wrappers from C++ files.

  13. Frank Dellaert

    OK. Still need a pull-request based on the branch, and then I can approve and merge after Jenkins verification.

  14. Simon Julier reporter

    Done. I also see that I use nano too often and automatically typed "y" when trying to save the file on change description.

  15. Log in to comment