Resolution Options
I think these are the possible resolutions:
1. Ignore the issue and whistle a happy tune. Nobody is complaining.
2. Document the requirement and behavior and create a guthub issue; defer until refactoring pass. [Recommended]
3. Modify the code.
I think there's an easy fix that maintains the current behavior and is inexpensive. Use a local buffer to extract the offset list before setting the calibration posture and processing the offset list. This will free the newCmd buffer for setting the calibration posture and allow filtering of the offset list.
At the time the list extraction begins, we know the token is T_CALIBRATE and the length of the command in the newCmd buffer (cmdLen).
The nominal form of the offset list is
< offset list > := < joint idx > DELIMITER < offset >
| < joint idx > DELIMITER < offset > < offset list >
< joint idx > := < number >
< offset > := < number >
DELIMITER := SPACE
| COMMA
} TAB
The joint index should be in the range [0, DOF), i.e., zero to one less than DOF. The offset should be in the range [-120, 120] but nominally should be (-15, 15).
The offset list size is variable, i.e., the number of elements in the list is unspecified, but nominally should have no more than DOF elements. The order of the elements is unspecified as well.
We need to extract only the valid offsets from the list; we can discard invalid list elements. We only need a buffer large enough to hold the offsets for valid joints.
Given that, the simplest way I can think of to do this without a vector
bool extract_offset_list(
char* buffer // source buffer
, int8_t* list // offset list
, const char* delimeter // token delimeters
)
{
char* pch{ strtok(buffer, delimeter) };
while (nullptr != pch) {
int8_t idx{ int8_t(atoi(pch)) };
pch = strtok(nullptr, delimeter);
int8_t offset{ (nullptr == pch)
? int8_t(127)
: int8_t(atoi(pch)) };
if (0 <= idx && idx < DOF) {
list[idx] = offset;
}
pch = strtok(nullptr, delimeter);
}
return true;
}
usage:
char newCmd[]{ "0 1 8 9 10 11 12 13 14 15 15 16" };
int8_t list[DOF]{};
memset(list, 127, sizeof(list)); // default value; (unmodified)
const char* delimeter{ " ,\t" };
extract_offset_list(newCmd, list, delimeter);
// ...load "calib" posture if necessary
// ...apply modified offsets from list
The behavior of strtok allows the implementation to handle malformed input, e.g., c0,,1,,8,,9,,... Whether that is desirable is an open question. Input syntax validation can be expensive and is not generally performed in the codebase.
The memory needed is stack based, small, and should be available. Further testing is needed since reaction is a critical function.
Edit: fix function call name
Addendum: I've submitted issue #16 on this in the OpenCatEsp32 repository