The remap sends the command through a square root function while normalizing to 1, to preserve the command range. Something like this:
// square root remap, command range is 0-255:
command_out = 255.0*sqrt(command_in/255.0);
This keeps the maximum command at 255 and the minimum at 0, but shapes the intermediate values to be a square root function. I don't actually do it like this because square root on a microcontroller is a horrible thing. Both the input and the output are 8-bit integers, and I have plenty of memory, so I use a look-up table instead:
// I'm a horrible person, generating my LUT at run-time:
unsigned char SQRT_LUT;
for(unsigned int i = 0; i <= 255; i++)
SQRT_LUT[i] = (unsigned char)(255.0*sqrt((float)i/255.0));
...and later, in the loop...
command_out = SQRT_LUT[command_in];
Because it's an 8-bit integer table, there is some quantization near the extremes, but my upper and lower throttle limits (100 and 230) constrain it to a well-behaved part of the curve:
After implementing the remap, I noticed a significant improvement in the performance. For one, some of the high-frequency oscillation is gone. It doesn't seem to wiggle back and forth quickly when it's just hovering. It's also easier to hold it at a given altitude, probably due to the more linear stick-to-force relationship. I don't think it's just placebo effect, but who knows?
I also made one other ugly hack. One motor has been consistently and annoyingly slow compared to the other three, causing the roll axis to be hard to fly, especially as the battery drops below about 7.4V. I just multiplied this motor's rate gain by 1.3. I have no justification for this value, but it helps. Maybe I will replace that motor and ESC at some point. Here's some new video:
I can keep it in the air indefinitely in a small room, as long as the battery is above 7.4V. Below 7.4V, the roll axis still gets soft and it's hard to not crash into things. So for now I live with flying just a bit more than half the battery capacity. Even Charles can kinda fly it now. So it must be a little more stable.
The two hardest parts about flying it are maintaining altitude and remembering which way it's pointed. While I think you can learn to deal with both of these, I would like it to be easy enough for anyone to pick up and fly. I have, waiting to be installed, a sonar module that can be used for closed-loop altitude control. Then, the stick would control a climb rate or descent rate, but with no input it would hold altitude and you can focus on flying the rotational axes. I also have yet to implement the magnetometer on the new IMU, which can be useful for holding heading so you don't have to deal with yaw.
I really shouldn't be spending this much time on quadrotors, though. I'm pretty sure I had other things I was supposed to be working on. On that note...