I saw a recent Skyentific video and decided to have a try at it myself, check out the result:
This is part of a continuing series on updated diagnostic tools for the mjbots quad A1 robot. Previous editions are in 1, 2, 3, 4, 5, 6, and 7. Here I’ll be looking at one of the last pieces of the puzzle, synchronizing the video with the rest of the telemetry.
As mentioned previously, recording video of a robot running is an easy, cheap, and fast way to provide ground truth information on all of the sensors and actuators. However, it is only truly useful if it can be accurately synchronized in time to the other telemetry streams for the robot.
This was part of the puzzle that I spent a long time thinking about before I got started, as there are several possible options that seemed like they could maybe work:
The concept here would be to put an LED beacon on the robot that is visible from all angles. It could strobe a synchronizing pattern, like the output from an LFSR which could be identified in the subsequent video frames.
Pros: This should be able to give frame accurate synchronization, and works even for my 1000 fps camera which can’t record audio.
Cons: It is hard to find a good place to mount a light which could be observed from all angles. The top is the best bet, but I have plans to attach further things there, which would then render synchronization infeasible.
In this concept, I put a microphone on the robot and have it record audio of the environment during its run. Then standard audio synchronization algorithms can be used to align the two streams. I actually included a microphone on the most recent version of the pi3 hat to potentially use this approach.
Pros: This has no visibility requirements, and should be able to give synchronization accuracy well under a single frame of video.
Cons: Getting the microphone data off the pi3 hat was looking to be moderately annoying, as the STM32 which it is connected to is already streaming IMU and RF data back to the robot over its single SPI bus. When I brought up the board, I verified I could get 1kHz audio off, but that isn’t enough to be useful.
This was the idea I had last, and what I am using now. Here, I slap the side of the robot in a semi-random pattern during the video. That results in an audio signature in the video, as well as lateral accelerometer readings.
Pros: No additional hardware or software is required anywhere on the robot.
Cons: This has worse accuracy than pure audio, as the IMU is only sampled at 400Hz and doesn’t perfectly correspond to the audio found in the video.
I took a stab at the IMU version, since it looked to be the easiest and still gave decent performance. I made up a simple python tool which reads in the robot telemetry data, the audio stream of a video file, and lets the user select rough ranges for the audio and video streams to work from.
It then uses
scipy.signal.correlate to do its best job of finding an alignment that best matches both data streams, producing a plot of the alignment.
As you can see, the audio rings out for some time after the IMU stops its high frequency response, largely due to the mechanical damping of the robot. However, it is enough for the correlation to work with and give frame accurate results.
In previous posts of this series, I covered some diagnostics improvements I’ve made to help work on more advanced gaits for the mjbots quad A1 (1, 2, 3, 4, 5, 6). This post will cover the last major new piece of diagnostics I added to tplot2, 3d rendering of telemetry data.
While it should be obvious, I’ll give a little exposition. tplot2 in its state prior to this could show a “tree view” of all data logged in numeric form. It had a “plot view” which let you plot any single floating point scalar vs time. As of recently, it could also render video associated with a given point in time in the log. However, as anyone who has ever tried to debug a 3d dimensional software application, much less a 3d dimensional robot, can attest, debugging with scalar numbers and time plots is only productive for a very limited range of problems.
I’ve been wanting to extend my plotting tools with 3d rendering for some time, and now have gotten around to a minimal first pass. The logic itself isn’t terribly complicated. A separate GL Framebuffer object is created in order to render into a texture, then pretty standard GL vertex and fragment shaders are used to render some triangles and lines. Initially, I’m just doing the robot body, the commanded and actual feet positions, speeds, and forces, and an estimate of the ground underneath them.
While there is a lot of room for improvement here, both in terms of the visual quality of the existing renderings, and new features that could be rendered, this is already proving itself to be invaluable in diagnosing longstanding problems with the gait motion.
This is part of a continuing series on diagnostics tooling for the mjbots quad series of robots. The previous editions can be found at 1, 2, 3, 4, and 5. Here, I’ll cover the first extension I developed for tplot2 to make it more useful to diagnose dynamic locomotion issues.
Diagnosing problems on robots is hard. The data rates are high, sensing is imperfect, and there are many state variables to keep track of. Keeping track of problems that are related to erroneous perception are doubly challenging. Without a recording of the ground truth of an event, it can be hard to even know if the sensing was off, or if some other aspect was broken. Fortunately, for things the size and scope of small dynamic quadrupeds, video recording provides a great way to keep a record of the ground truth state of the machine. Relatively inexpensive equipment can record high resolution images at hundreds of frames a second documenting exactly where all the extremities of the robot were and what it was doing in time.
To take advantage of that, my task here is to get video playback integrated into tplot2, so that the current image from some video can be shown on the screen synchronized with the timeline scrubber.
Making it happen
Here I was able to use large amounts of the code that I developed for the Mech Warfare control application. I already had the ability to render ffmpeg data to an OpenGL texture. The missing pieces I needed were getting that texture into an imgui window and adding seek support.
The former was straightforward. imgui has a
ImageButton widgets which allow you to draw an arbitrary OpenGL texture into an imgui widget.
The latter was a little more annoying, only because the ffmpeg API had a slightly unusual behavior. Even after
av_seek_frame was called, one frame from the old point would still be emitted. This confused my seeking logic, possibly causing it to ignore frames. However, after discarding that one stale frame, it worked seemingly just fine.
Next I’ll cover the last major piece I added to tplot2 to help with issue diagnosis.
I made up a YouTube video showing the techniques I used when manufacturing the beta edition of the qdd100 servos TODO link. Check it out: