If you read my previous post, I was talking about this new open source library I’ve created that allows you to embed a web server in your C++ application so that you could modify variables inside of it. I had created it for our FIRST Robotics team so that we could use it to tune things on our robot (and its been extremely useful for that) and use it for simple data acquisition. Of course, driving a robot is nothing more than changing variables… so I thought it would be a neat demo to set it up so that it could be driven by the web interface.
Here’s a video of our robot being controlled via the WebDMA interface:
When walking around during the Boston Regional, I had been talking to some people about code, and they mentioned that LabView was great because they could tune their PID controllers on the fly while the robot was operating. So I thought to myself, “why can’t I do this with C++?”. And… so I did. WebDMA was created to allow our FIRST Robotics team to tune our robot in an easy to use and intuitive way via any modern web browser.
Using C++ operator overloading, WebDMA provides proxy objects that your application can use as normal variables which can be manipulated or displayed by your application via a configurable jQuery/javascript powered Web 2.0 interface hosted by an lightweight embedded web server.
Despite that WebDMA was specifically created for use in FIRST Robotics on the NI-cRio/vxWorks platform, it uses the Boost ASIO portable networking library and Boost Thread portable threads library and is usable on any platform supported by these Boost libraries (tested on Boost 1.38, requires a patch for vxWorks).
The FIRST Robotics Competition is using the National Instruments cRio platform for the robot controller this year, and the operating system on it is vxWorks 6.3. After we participated in the competition, I had gotten a great idea involving putting a webserver on the robot so that it would be easier to tune various parameters on the robot (which I will be releasing soon).
I decided to use Boost::Asio for the networking layer since I had been meaning to write something using it for awhile anyways, and since its portable I could do the initial development on my home computer and then easily (at least, ideally) transfer it to another platform. I also decided to use Boost::Thread for the same reason. If you haven’t used Boost before, I highly recommend it — it has a lot of well-written and useful C++ header-only libraries.
Unfortunately, vxWorks is a bit different than ’standard’ POSIX/*nix systems, so there are a number of patches one needs to make to Boost 1.38.0 in order to compile. I’ve submitted the patches to boost, so hopefully by the time 1.39.0 rolls around you won’t need this.
You can download the full patchset needed from my FRC resources page. Download it.
For years I’ve hated cygwin (not for any particular reason, I just don’t like it) and have generally avoided using it because of that — but I’ve finally found a good alternative if you want useful *nix tools on Windows. Its called GNUWin32 and its a bunch of GNU utilities that have been ported to windows, and they’re quite lightweight also.
Its pretty sweet, I’ve actually had grep installed on my computer for quite awhile now, and just recently started installing more of these packages as my needs have evolved. I’d highly recommend it. The key thing to do is to add the bin directory to your path, so that way its accessible from cmd by default without having to screw around with typing out the full path name or anything.
So, while working on the Kwarqs robotics code, I found a useful solution to implementing the singleton pattern in c++ that I believe avoids the static initialization fiasco (with a small restriction) *and* doesn’t leak memory.
What I’ve created is a template class that takes a pointer to a pointer at construction, and deletes the pointer as it is getting destructed. While you cannot guarantee when the class is created due to static initialization issues, from what I can see the C++ standard does guarantee that all intrinsics are initialized before other items are constructed. By using a pointer to a pointer, we can guarantee that the location of the object will be the same (and thus destruction will happen correctly), and provided we initialize the static variable to NULL we can also guarantee that initialization will happen correctly.
Warning: A key assumption made by this class is that the static object is only accessed during the normal scope of the program — ie, the object that this class contains a pointer to a pointer to should not be accessed by anything that could be called after main() is complete. For some code bases, this can be very tricky to enforce.
Usage of the class is quite trivial:
SomeType * SomeType::m_instance = NULL;
StaticDeleter someTypeDeleter(&m_instance);
// example singleton initialization
SomeType * SomeType::GetInstance()
{
if (SomeType::m_instance == NULL)
SomeType::m_instance = new SomeType();
return SomeType::m_instance;
}
And the implementation of the static deleter is also quite trivial (but I’ve provided a downloadable version as well), check it out:
// (C) 2009 Dustin Spicuzza, released under modified BSD license
template
class StaticDeleter {
public:
StaticDeleter(TypeToDelete ** ptr2ptr) :
m_ptr2ptr(ptr2ptr)
{}
~StaticDeleter()
{
if (*m_ptr2ptr)
delete *m_ptr2ptr;
}
private:
TypeToDelete ** m_ptr2ptr;
};
So after *far* too much time spent on this, I am happy to announce the release of my WPILib Test Harness! For those who aren’t aware, WPILib is the name of the C++ library that FIRST gives to FIRST Robotics Teams to control the robots. The control system is a PowerPC running on a cRio platform designed and produced by National Instruments.
It had occurred to me towards the end of the build season this year that it was really annoying that I could only easily test code while our team was meeting, and of course I stay up late (as evidenced by this post time). So I wrote some stubs, but at some point I realized it would just be easier to make a giant stub for WPILib, since its just a set of classes with some hardware interfaces. It was extremely useful, and as I evolved it I was even able to find bugs in WPILib and the program for our bot.
At some point I decided to bring it in the direction that it is now, and I’ve spent the last week adding things and making the GUI a bit shinier. I’m pretty happy with the results so far, but theres a long way to go before every bot program will run under it. There’s a lot of things that do work, but there’s also a lot of things that don’t work. Read the rest of this entry »
Ever got one of those *really* annoying glibc errors that don’t give you a whole lot of information except “something bad happened, and it was memory related, but we’re not going to tell you where the problem is!”? You know, in the form of
*** glibc detected *** ./test: double free or corruption (out): 0x0000000001e52440 ***
======= Backtrace: =========
/lib/libc.so.6[0x7f27a9fd5a58]
/lib/libc.so.6(cfree+0x76)[0x7f27a9fd80a6]
./test[0x401e51]
./test[0x401e83]
./test[0x402118]
./test[0x402159]
./test[0x40155b]
./test[0x40167d]
/lib/libc.so.6(__libc_start_main+0xe6)[0x7f27a9f7a466]
./test[0x400cd9]
======= Memory map: ========
... and so on ...
I’ve encountered this cryptic and annoying error (I mean c’mon, usually the memory addresses referenced in the trace don’t resolve to anything in gdb) a few times for really random and weird memory-related errors, many times when I’m doing something with the STL.
Turns out, you can define __GLIBCXX_DEBUG in your program (using -D__GLIBCXX_DEBUG on the g++ command line), and instead of an annoying message you may get an assert that is far more helpful and looks like this:
/usr/include/c++/4.3/debug/vector:267:error: attempt to access an element
in an empty container.
Objects involved in the operation:
sequence "this" @ 0x0x7fff5ee0f420 {
type = NSt7__debug6vectorIiSaIiEEE;
}
Now at least you know what you did wrong. However, for optimal usage you should be attached with GDB, and then as soon as the error occurs you can do a backtrace with the debugger and you should know exactly where the bug is. The only caveat is that there is a noticeable performance hit when you enable this (especially if you use the STL heavily), so in general you don’t want to define it all the time.
Hope that saves you some time! I know it helped me!
Our robot this year uses a ’swerve drive’ mechanism, with 4 independently steerable wheels. I wasn’t quite sure exactly of the best way to describe the robot’s motion in terms of basic parameters (speed, heading, rotation) , so I went google searching. I found a PPT by Ian Mackenzie talking about different types of omnidirectional drive systems, and it was extremely helpful.
After thinking about it some more, I created this spreadsheet to help describe the motion parameters to the students I was working with. Its pretty sweet — it uses scatter plots to show the angle of each wheel and the ideal velocity to obtain the motion desired based on the speed/rotation/angle parameters of the overall robot motion. The implementation in C++ was straightforward after that, and it worked out extremely well (unfortunately there is the whole issue of controlling it intuitively with a joystick… we haven’t quite got that down yet).
This is another resource that I’ve created for the Kwarqs FIRST Robotics team this season that I’ve found useful, and hopefully others will find it useful as well.
This particular program is stupidly simple, but really nice to have around in case you think your driver station is being screwy, or you want to verify that your switches work *before* running your actual code on it (not that you would run something without testing it, right? ). As you can see from the code, it displays the driver station inputs on the LCD panel of the driver station. It uses a modified version of the DriverStationLCD class posted at http://thinktank.wpi.edu/article/144
While working on some code for the FIRST team that I’m on, I had decided we were going to need PID control for some portions of our robot. Unfortunately, I have not done a lot of this stuff.. I took a control systems theory class in college, but I never quite saw the value of it at the time (which, I’ve come around now that I’ve seen some practical applications). So, to understand how it works more, I created this spreadsheet with adjustable P/I/D parameters. I found this to be a useful tool in understanding the output of a PID control system.
Of course, its strictly an ideal model and not particularly realistic (try setting the P parameter to 1)… but its primarily useful for getting that basic understanding. Theres a number of ways it could be improved… feel free to improve it.