Out of static memory for variable allocation

Hi,
I am currently writing a replay autonomous (I am an experienced programmer, and I know what I am doing, the only reason we are doing a replay is because we don’t have time or a field to test it on). My replay algorithm works well, but I am unable to add the actual replay data to my program. Right now, I am storing them as follows:


//D1 is time, one reading every 20ms
//D2 is button/ch

//Autonomous
static const byte f_auton_ch   [750][2] = {.....}
static const bool f_auton_btn [750][6] = {.....}

//Skills
static const byte f_prog_ch     [3000][2] = {.....}
static const bool f_prog_btn   [3000][6] = {.....}

But I end up with a


Out of static memory for variable allocation

error on the last declaration. Is there any way I can shrink these huge arrays down? I am already using bytes for the joysticks, and bools for the buttons. These are the bare minimum channels and buttons I need. (That is if my team can get an arm/claw working next week, if not, I can cut out 4 buttons). Any help is appreciated.

Some things you can look at:
-Booleans do not necessarily take 1 bit in memory. The compiler can decide if they should be packed or not. If they are not packed, you can pack them yourself.
-Do you need both programs stored at the same time?

First, I wouldn’t do re-run this way, but if what you have is working for you, it’s fine to stick with it.

That said, if you want to use less storage you could compress the data for storage and decompress it when reading.

If you’re interested in trying that approach, I could help in a day or so.

To this point, you can used a fixed sized type and bit operators for the same effect and guarantee that no memory is wasted. Please see: In C how much space does a bool (boolean) take up? Is it 1 bit, 1 byte or something else? - Stack Overflow

Also, Eric’s second point is critical here.

A couple other things to consider:

  • Do you use all 15 seconds of auton and prog skills? If not, remove memory, even a few seconds from each helps
  • Button recording does not necessarily require a 3000 * 6 array of bool for all six buttons. You could do some data proccessing of button when recording and pack it all up. This way you could have a single array of 500 bytes for prog skills and each bit stores a press. If you are looking for an example of how to do this, this program uses something similar to do a large sieve of eratosthenes you can go off of.

@Eric_J What do you mean by packing them myself? Storing them as bitmasks?

You could store 8 booleans as a single byte. It would be more complicated to store/retrieve them, but it would save space.

As others have stated, there are better ways to do the data collection. When I wrote my replay program 6 years ago, I used a different method to get around the memory limitation, and could store close to 10 different autonomous routines. I don’t want to give away the method though, but you should be able to figure it out.

Do you mean the Vex Filesystem? I don’t know much about that and I don’t really have time to learn it. I will try using a byte and see how that goes.

@lathashivakumar, I have a couple of questions.

How are you planning for this to work? Are you planning to record a run on the field at the competition event, save the data in real time as the driver is moving, and then play it back a few minutes later all at the same event?

Do you intend the stored joystick/controller data to persist only while the Cortex remains powered?

Most people don’t do re-run that way. It can be more convenient to get the data out of robot by writing to the debugStream and capturing that over the wireless programming link. Often, the captured data is processed and used it to create an autonomous routine. The generated autonomous routine is then pasted into a competition template in the appropriate place, compiled, downloaded, and run.

Your way (which I think I’ve guessed correctly above) should work fine, but the stored values will only persist while the Cortex remains powered.

If that’s okay with you, then the only issue is to store the data compactly enough that you won’t run out of memory.

If you want help on compact storage methods, or on getting your recordings to persist by taking the data off-cortex, processing it, and getting it into either pre-loaded storage arrays or prebuilt code, let me know.

Actually, my recording program prints it all out to the debug stream (in this format, conveniently, so I can directly save the debug stream as a .h file). Then I just use an #include to include this data in my compiled program. This way, the data is saved as part of the program, survives power cycles, and is cortex-independent (so no file-system trickery). The algorithm I made just reads the array with the joystick values and emulates my driver control code so that it reads from the special globals I made. The issue comes with adding my array with data to the program.

Got it. That’s very workable, and that’s why you’re just concerned about how to fit it into static arrays.

So, you just need to store the data more compactly, then.

Yes. I followed Eric’s advice and stored the booleans as bitmasks (bytes), so now I am able to store everything. But thanks for the help anyway!

Just out of curiosity, is there a way to further compress it? I thought of sparse arrays, but I didn’t know the best way to implement a Set datatype in ROBOTC.

Incidentally, my idea is exactly what you were talking about, except for the fact that I will only record once. I will go to the event, and record my autonomous and programming skills there. I am part of a private team, and we don’t have access to a field :slight_smile: So you were perfectly correct!

Good luck! Glad Eric’s advice got you going.

Glad the bitmask was able to sort it out. In terms of ways to get even smaller

only storing skills OR autonomous at a time would save a lot
You could save about 1/3 of your used space if you were willing to only allow joystick values in multiples of 16. ( if you really wanted to try to be clever maybe 12)

You could sample less often.

You are going to process the data in a streming fashion, no random access necessary.
That way and given the nature of the data (you are hardly changing the controls every 20ms), you could easily implement a Run Lenght Encoding compression - prefix every sequence of the same values by the count. The “consumer filter” (during recording) would remember last value and don’t emit (store it to the output array) till a different value comes, so it would know and store the count (N) before the value. The “producer filter” (during playback) would just yield the same value N times before moving on.
If you learn that your values have noisy bursts that won’t compress (many cases of lengths of 1), you can go more fancy and have 2 length encodings, negative denoting sequence of changing values, positive for a repeated value, though that’s a little harder to compress in a streaming fashion.
Example:

Joystick reading: 0 0 0 0 50 101 120 120 120 120 120 118 60 0 0 0 0
Compressed data:  4 0  -2 50 101 5 120            -2 118 60 4 0

The above works for generic data. For a domain specific data that you can mess with a little, imagine repurposing the lowest bit of data as a flag of count vs. value:

Joystick reading: 0 0 0 0 50 101 120 120 120 120 120 118 60 0 0 0 0
Compressed data:  9 0     50 100 11 120              118 60 9 0

(read as: 9=2*4+1, lowest bit set, so it is a start of the run of length 4, value 0. 101 has to be rounded down to 100 to have lowest bit clear)