Closed PeterBowman closed 3 years ago
- Start the motion: how?
Tiny grain of salt, regarding options we've contemplated in the past (I like the second one slightly better):
position
or something like idle
), then send motion start command immediately upon switching to position direct
mode.PS: There was a third option, via IRemoteVariables
, which itself can ramify into many options. I'm still more inclined to the second of above due to all the issues this would involve.
Current implementation looks promising, has been successfully tested via examplePositionDirect app.
Config:
Workflow:
IRemoteVariables
interface. Supported options are mode
(either pt
or pvt
) and periodMs
(interpolation time, in milliseconds):
set ivar mvar all (linInterp (enable 1) (mode pt) (periodMs 50))
LinearInterpolationBuffer
class) instead of using CSP setpoints.IPositionDirect::setPosition
pushes the arriving setpoint into an internal FIFO queue. Clients may want to either burst all offline-generated trajectories into this queue in a single shot or fill it gradually.IPositionDirect::setPosition
, then the cycle starts anewTested with both PT and PVT submodes, interpolation time period ranging from 5 to 50 milliseconds, on a single node. I wonder whether bursting setpoints to six nodes at once would saturate the CAN bus.
See:
As mentioned above, the linear interpolation submodes are interfaced via IPositionDirect
. The following options have been considered and discarded, for future reference:
Fully interact via IRemoteVariables
, i.e. load points into the internal queue and send the start command without having to resort to IPositionDirect
. This solution has several drawbacks due its poor/flawed support via ControlBoardWrapper, see https://github.com/roboticslab-uc3m/yarp-devices/issues/208. It could pose an advantage due to the fact that it allows sending velocity data and even different periods per setpoint along with position data. However, there is hardly a compelling reason to vary periods between acquisitions, and velocity is usually obtained via differentiation of consecutive positions anyway. This effort can be easily transferred from the caller application to the LinearInterpolationBuffer
class itself.
Use mixed mode (https://github.com/roboticslab-uc3m/yarp-devices/issues/215). Per http://wiki.icub.org/wiki/Control_Modes: "the mixed control (VOCAB_CM_MIXED) mode allows the user to send position and velocity commands on the same joint (to perform saccadic movement, for example)". See previous point regarding velocity data. Also, position and velocity commands would be sent separately, more checks would be involved (position data arrived, but velocity didn't) and so on.
Velocity setpoints in the PVT submode are currently obtained via arithmetic mean of the mean velocities between three consecutive points. That is, the mean velocity is obtained between the current and the previous setpoints in the queue, same for the next and the current setpoints, and then both results are weighed (same period, so this is as simple (A+B)/2).
(...) velocity is usually obtained via differentiation of consecutive positions anyway
I wonder if this solution could yield better results in a cubic interpolation (regarding position data). Surely it is less convolute, must check its "jerkiness".
I wonder if this solution could yield better results in a cubic interpolation (regarding position data). Surely it is less convolute, must check its "jerkiness".
This MATLAB script performs cubic interpolation on a randomly generated curve: splinetest.zip. It also plots y (position) against x (time), therefore slopes are instantaneous velocities.
Three different approaches regarding slope values are depicted in the following figure. Cyan means zero slope on boundaries and blue points, red line represents the differential approach (mean slope between current and previous point), and black line corresponds to the currently implemented arithmetic mean approach (weighed result of previous and next slopes):
Out of sheer curiosity, MATLAB's spline
function applied over the full x range yields the following result (red line) versus the arithmetic mean approach (black line) obtained by applying the spline
algorithm on each interval:
I definitely like the implemented approach.
Fully interact via
IRemoteVariables
, i.e. load points into the internal queue and send the start command without having to resort toIPositionDirect
. This solution has several drawbacks due its poor/flawed support via ControlBoardWrapper, see #208. It could pose an advantage due to the fact that it allows sending velocity data and even different periods per setpoint along with position data. However, there is hardly a compelling reason to vary periods between acquisitions, and velocity is usually obtained via differentiation of consecutive positions anyway. This effort can be easily transferred from the caller application to theLinearInterpolationBuffer
class itself.
I'm considering this option (again), mainly because of:
IRemoteVariables
can guarantee that we issue the robot-wide motion start command simultaneously.IRemoteVariables
interface calls on a multiple-wrapper configuration (e.g. several network wrappers talking with a single CanBusControlboard) is misleading, indeed: I could interface through any port (/teo/leftArm, /teo/rightArm) and yet target any started node on the robot. However, this cannot be avoided and I'm already doing this in order to select the interpolation submode and such.Considering that from path-planning now we can have a nice big Bottle that encapsulates a Trajectory:
IRemoteVariables
Note: problems reported by ControlboardWrapper such as Error while trying to command a streaming position direct message on all joints are caused by hardware faults and elevated through the current control mode check. See CHECK_MODE
in:
- Long term: PR on YARP controlboard interfaces and network wrappers, perhaps involving these classes I just discovered: https://www.yarp.it/namespaceyarp_1_1rosmsg_1_1trajectory__msgs.html
Note that this is in fact a rosmsg
.
After a long chat with @jgvictores in the aftermath of https://github.com/roboticslab-uc3m/yarp-devices/issues/254#issuecomment-776256880, we've summarized the main use cases for the variety of IPositionDirect
implementations. First, a few words on the principles behind CSP and legacy linear interpolation (a.k.a. PT/PVT):
setPositions
to the robot) must be tightly coupled period-wise wrt. to the internal synchronization period. As observed and reported in https://github.com/roboticslab-uc3m/yarp-devices/issues/254#issuecomment-776256880, even a small drift in thread synchronization leads to degraded motion behavior. It is important to note CSP seems to be implemented with an internal, 9 or 10-element buffer, so there is always a delay between setPositions
and resulting joint motion.I am going to propose an asynchronous PT/PVT implementation in clear contrast to CSP, which is probably going to stay the way it is now. Going async means that the drive will not expect new setpoints at a fixed, preconfigured rate (we used to work with a period of 50 milliseconds). Instead, the delay between successive points will be computed on-the-fly, i.e. as soon as TechnosoftIpos receives point n+1, it substracts current time from the time point n was received and sets the "T" component accordingly. In short: if n+1 arrived 47 ms later than n, instruct the drive to perform n+1 in 47 ms. In consequence, new setpoints may be sent in arbitrary time periods.
This solution aims to decouple external control applications from the internal point processing rates in synchronous drive modes. In conclusion, expected use cases are:
/sync:o
port (name not final) and produce new commands accordingly. Rate is fixed. Needs extra work to adapt the same code for simulation (no sync port). Might skip some points due to network issues.CanBusControlboard
instead of remote_controlboard
. Probably needs extra code to account for robot initialization.Once implemented and tested, these guidelines should land in teo-developer-manual.
As a side note, implementations could take advantage of some filtering. See the iCub's collection of utilities.
External controllers must implement some sort of callback mechanism listening to the new
/sync:o
port (name not final) and produce new commands accordingly. Rate is fixed. Needs extra work to adapt the same code for simulation (no sync port).
In fact, the sync port can be easily emulated with yarp sample --output /sync:o --period 0.05
, though (or --rate 20
).
Mostly implemented at https://github.com/roboticslab-uc3m/yarp-devices/commit/2308f03ced8aebe9f94c7c3e10967062f07048fc, needs testing. Main remarks regarding PT/PVT submodes:
See https://github.com/roboticslab-uc3m/yarp-devices/issues/198#issuecomment-487279910 regarding buffer sizes. Default buffer low limit has been set to 4 points.
Workflow:
IPositionDirect
, initial drive configuration ensues.setPosition(s)
, each point is stored in the internal queue along with the current timestamp.setPosition
at the desired command rate. New points are placed at the end of the internal (FIFO) queue.setPosition(s)
, go back to step 2 and repeat the whole sequence.In order to implement asynchronous PT/PVT, the internal queue stores setpoint-timestamp pairs. The exact time at which each point is placed in the queue is captured in order to obtain the difference between successive points. For instance, if point n1 was sent by the user at timestamp t1 and n2 at t2, then the result of t2-t1
is used as the time component in the ip setpoint for n2. Note that there is no such reference to obtain the time component for the very first point in the queue (before motion start). It is assumed that t1 is equal to t2 and a dummy point is made up (but not placed in the drive's buffer) from the current joint position in order to obtain the velocity for n1 in PVT submode. In addition, I am storing an initial timestamp to compensate for rounding and accumulation errors in the conversion from seconds to period samples.
To be considered (TO-DO list):
setPosition
if the HW buffer has been already declared empty, in which case disable ip mode and keep loading new points in the internal queue until the full buffer size is reached, then replenish. Currently, because of the buffer-low check evaluating before buffer-empty, more points could be sent despite commanding the drive to disable ip (the buffer accepts points anyway), and upon activation the next batch (9 or 7 points) would be wrongly calculated. Done at https://github.com/roboticslab-uc3m/yarp-devices/commit/10b09bbc938b1f603a1891d3e473f0af384c6373 and https://github.com/roboticslab-uc3m/yarp-devices/commit/0e38541363efdf441412426b239914b86f666305.Mostly implemented at 2308f03, needs testing.
Not working. Rolled back to https://github.com/roboticslab-uc3m/yarp-devices/commit/0137786d8e985b15c535f3d76924c5e6b6315310 and tested examplePositionDirect successfully. The implementation is not final, though, since I want to consider the previous TO-DO list. I have learned that the drive reports not the current, but the next integrity counter expected, which makes impossible to know for sure the current number of points in the HW buffer and thus to implement this idea:
Use integrity counter to determine next batch size instead of relying on the internal queue length?
Logs:
[warning] LinearInterpolationBuffer.cpp:86 operator()(): Prepared setpoint with ic 0
[warning] LinearInterpolationBuffer.cpp:86 operator()(): Prepared setpoint with ic 1
[warning] LinearInterpolationBuffer.cpp:86 operator()(): Prepared setpoint with ic 2
[warning] LinearInterpolationBuffer.cpp:86 operator()(): Prepared setpoint with ic 3
[warning] LinearInterpolationBuffer.cpp:86 operator()(): Prepared setpoint with ic 4
[warning] LinearInterpolationBuffer.cpp:86 operator()(): Prepared setpoint with ic 5
[warning] LinearInterpolationBuffer.cpp:86 operator()(): Prepared setpoint with ic 6
[warning] LinearInterpolationBuffer.cpp:86 operator()(): Prepared setpoint with ic 7
[warning] LinearInterpolationBuffer.cpp:86 operator()(): Prepared setpoint with ic 8
[warning] TechnosoftIpos.cpp:394 interpretPtStatus(): Got ic 9
[info] TechnosoftIpos.cpp:58 reportBitToggle(): [pt] Buffer is full. (canId: 26)
[info] TechnosoftIpos.cpp:58 reportBitToggle(): [status] Bit reset: Target reached. (canId: 26)
[info] TechnosoftIpos.cpp:58 reportBitToggle(): [status] Interpolated position mode active. (canId: 26)
[info] TechnosoftIpos.cpp:58 reportBitToggle(): [MSR] Bit reset: Target command reached. (canId: 26)
[warning] TechnosoftIpos.cpp:394 interpretPtStatus(): Got ic 9
[info] TechnosoftIpos.cpp:58 reportBitToggle(): [pt] Buffer is not full. (canId: 26)
[warning] TechnosoftIpos.cpp:394 interpretPtStatus(): Got ic 9
[info] TechnosoftIpos.cpp:58 reportBitToggle(): [pt] Buffer is low. (canId: 26)
[warning] LinearInterpolationBuffer.cpp:86 operator()(): Prepared setpoint with ic 9
[warning] LinearInterpolationBuffer.cpp:86 operator()(): Prepared setpoint with ic 10
[warning] LinearInterpolationBuffer.cpp:86 operator()(): Prepared setpoint with ic 11
[warning] LinearInterpolationBuffer.cpp:86 operator()(): Prepared setpoint with ic 12
[warning] LinearInterpolationBuffer.cpp:86 operator()(): Prepared setpoint with ic 13
[warning] TechnosoftIpos.cpp:394 interpretPtStatus(): Got ic 14
[info] TechnosoftIpos.cpp:58 reportBitToggle(): [pt] Buffer is full. (canId: 26)
[info] TechnosoftIpos.cpp:58 reportBitToggle(): [pt] Buffer is not low. (canId: 26)
[warning] TechnosoftIpos.cpp:394 interpretPtStatus(): Got ic 14
[info] TechnosoftIpos.cpp:58 reportBitToggle(): [pt] Buffer is not full. (canId: 26)
[warning] TechnosoftIpos.cpp:394 interpretPtStatus(): Got ic 14
[info] TechnosoftIpos.cpp:58 reportBitToggle(): [pt] Buffer is low. (canId: 26)
Sequence:
I'm quite positive that the integrity counter feedback can be used to implement a simple yet effective handshake.
PS newly generated logs of the full trajectory (old implementation at https://github.com/roboticslab-uc3m/yarp-devices/commit/8dbd67f3777dc8c60b7776ce096b166fcdbfe3dd): old-ip-21022021.txt. PS2 forgot that examplePositionDirect was prepared for sending the whole trajectory in a single batch, I instructed it to send them in regular intervals instead and it indeed worked: new-ip-21022021.txt. PS3 also successfully tested in PVT submode, but last setpoint did not have zero velocity: new-ip-pvt-21022021.txt.
However, IP status is reported via EMCY, which we map to TPDO2 with default inhibit time of 30 ms and no event timer (ref). A too high inhibit time can be limiting with regard to the IP command rate, i.e. the drive may not be able to report back its buffer state until up to 30 ms after the last setpoint was sent.
For this very reason, I am not considering this option anymore:
Following on the previous point, abandon batched point transmission and always send points individually (even before motion start) while attending to integrity counter updates?
PS my bad, TPDO2 is mapped to MER/DER:
I don't think there is an inhibit time setting for EMCY messages, so they are supposed to be triggered as soon as an emergency condition arises. From CiA 301 v4.2.0, 7.2.7.1, Emergency object usage:
Emergency objects are triggered by the occurrence of a CANopen device internal error situation and are transmitted from an emergency producer on the CANopen device. Emergency objects are suitable for interrupt type error alerts. An emergency object is transmitted only once per 'error event'. No further emergency objects shall be transmitted as long as no new errors occur on a CANopen device.
Anyway, I'd rather keep sending points in batches (as opposed to mimicking a handshake via individual requests and integrity counter checks) to avoid the saturation of the CAN network and timing issues.
While synchronous IP (interpolated position) works fine, asynchronous needs still more work:
Quick test: I have sent 2000 synchronous PT points that theoretically should have been executed in 20 seconds (period equal to 10 ms). I measured the time elapsed between buffer full and buffer empty signals and got only 19 seconds. There is a difference of 0.5 seconds if I supply half the number of points (period 20 ms), and 2 seconds if I double that amount (period 5 ms). It seems that the interpolation substracts like 0.5 ms from each setpoint.
ASWJ there is a bunch of use cases that involve us implementing yarp::dev::IPositionDirect
in one way or another:
Remote commands | Local commands | |
---|---|---|
Offline trajectory | Synchronous PT/PVT | Synchronous PT/PVT |
Offline trajectory (individual samples) | Asynchronous PT/PVT CSP (timer) |
Asynchronous PT/PVT CSP (timer) |
Online trajectory | CSP (sync port, timer) | CSP (shared state observer, timer) |
Definitions:
IPositionDirect::setPositions
, is executed outside TEO's PC and communication is achieved with usual YARP mechanisms (network control board wrapper pair).Methods:
IPositionDirect::setPositions
as many times as points are composing the trajectory, no delays in-between. Note that such application cannot be connected to our simulators since those expect new setpoints sent at arbitraty non-zero intervals.setPositions
, and applies a delay (the "T" term). This delay, if used within a for
loop, may vary, hence the "asynchronous" qualifier. This is not suitable for online trajectories because a buffer is involved, but you could use this anyway if you know what you're doing. Main issue at time of writing: the iPOS internal clock is slightly faster as it should be (https://github.com/roboticslab-uc3m/yarp-devices/issues/245#issuecomment-787459721).for
loop, for that case) to send new setpoints regardless of the online/offline nature of your trajectory, and the same code can address both real and simulated scenarios. As explained in https://github.com/roboticslab-uc3m/yarp-devices/issues/254, issue https://github.com/robotology/yarp/issues/2488 must be resolved upstream in order to minimize harsh transitions between skipped points. Even if solved, if you are unlucky enough and the command loop overlaps with the internal synchronization loop, you'll observe this same unwanted behavior. Perhaps some workaround could be arranged, pending investigation.Property
(local use case). Main drawback: you can only emulate the remote scenario on simulation (use yarp repeat
), not that bad though, but requires a bit more effort and lines of code.I've been doing my first tests, launching the trajectory of the issue https://github.com/roboticslab-uc3m/yarp-devices/issues/254#issue-791519244 -> test_elbow.zip and modifying your example examplePositionDirect.cpp to execute it in Synchronous PT/PVT (default in pt), reading the csv file.
Terminal 1: ./examplePositionDirect --robot /teo --batch
The result is that there is a loss of control when the arm returns. I've repeated the experiment executing it as before without --batch
parameter, which would lead to the execution of the trajectory in CSP mode (by default). The elbow runs good through the trajectory, although I imagine dragging the problems already mentioned in the issue #254.
Video in PT mode: https://youtu.be/yR4z7nSV7TE
Run the experiment again, uncommenting this line. Result of launchCanBus: launchCanBus.zip Video: https://youtu.be/VTqFul9036U
exactly, the first jump occurs on line 1686:
[debug] IPositionDirectRawImpl.cpp:13 setPositionRaw(): (0, -83.383257)
[debug] IPositionDirectRawImpl.cpp:13 setPositionRaw(): (0, -61.902524)
I've also seen this jump (although it doesn't arrive here) line 1750:
[debug] IPositionDirectRawImpl.cpp:13 setPositionRaw(): (0, -45.270002)
[debug] IPositionDirectRawImpl.cpp:13 setPositionRaw(): (0, -12.867257)
Applying a delay in the sending of 25ms (half of the execution period of 50ms by default) between one point and the next, the result is that it performs the execution of the trajectory successfully without any failure.
Added a delay between sending setpoints half the execution period:
if (!batch)
{
yarp::os::Time::delay(period * 0.001);
}
else
{
yarp::os::Time::delay(period * 0.0005); // -> period / 2
}
I've been reducing the period little by little until reaching 5 ms. It looks nice ^^! : Video: https://youtu.be/y6XFXQuruHs
I'm going to comment on some of the experiments that I've carried out to test the PT mode, executing an offline trajectory obtained from a CSV file. In this case, it's a trajectory captured from the mocap system and later processed through the teo blender project. Then, I've created a program that allows reading the csv file and sending the commands in PT / PVT mode to the robot or CSP to the simulator, following the example of the tests carried out previously.
I've tried to run the same csv both in the simulator (in CSP mode by default without the --batch
parameter), and in the real robot (in PT mode with the --batch
parameter). In both cases, the trajectory is executed with a period of 30 ms. The result is that in the real robot, a certain desynchronization between the joints (arms and trunk) can be seen even in certain joints of the arm itself, giving rise to an incorrect result of the trajectory. I've recorded both modes and tried to synchronize them, without modifying their real speed. Observe trunk movement when the robot is writing "TEO" and especially when it's tries to erase its name, making circular movements with the left arm. It seems that the turns are made in the opposite directions, probably due to a desynchronization with the sagittal motor of the shoulder.
@PeterBowman suggested to me to visualize the current value of yarp::os::time::now()
and can->getId()
after the lines https://github.com/roboticslab-uc3m/yarp-devices/blob/b5cc7e41e0ab54984e73d8acb520d0557cdad664/libraries/YarpPlugins/TechnosoftIpos/TechnosoftIpos.cpp#L423 and https://github.com/roboticslab-uc3m/yarp-devices/blob/b5cc7e41e0ab54984e73d8acb520d0557cdad664/libraries/YarpPlugins/TechnosoftIpos/TechnosoftIpos.cpp#L404 to appreciate the time it takes for each driver to execute the path.
The result of the values printed by terminal can be reviewed here. In conclusion, not all drivers execute the trajectory in unison or end at the same time.
Not accounting for trunk joints, time measurements for all upper body joints look as follows:
ID | start | end | diff | drift (overall) | drift (per point) |
---|---|---|---|---|---|
15 | 1615402270,575350 | 1615402392,332290 | 121,756940 | 1,243060 | 0,30318539 |
16 | 1615402270,575900 | 1615402390,460330 | 119,884430 | 3,115570 | 0,75989514 |
17 | 1615402270,577650 | 1615402389,416890 | 118,839240 | 4,160760 | 1,01481955 |
18 | 1615402270,579060 | 1615402393,494740 | 122,915680 | 0,084320 | 0,02056587 |
19 | 1615402270,579160 | 1615402393,491390 | 122,912230 | 0,087770 | 0,02140731 |
20 | 1615402270,581560 | 1615402390,127610 | 119,546050 | 3,453950 | 0,84242681 |
21 | 1615402270,575340 | 1615402391,761130 | 121,185790 | 1,814210 | 0,44249023 |
22 | 1615402270,575800 | 1615402390,606790 | 120,030990 | 2,969010 | 0,72414875 |
23 | 1615402270,577850 | 1615402390,770560 | 120,192710 | 2,807290 | 0,6847049 |
24 | 1615402270,579270 | 1615402389,414100 | 118,834830 | 4,165170 | 1,01589511 |
25 | 1615402270,580240 | 1615402391,979030 | 121,398790 | 1,601210 | 0,39053905 |
26 | 1615402270,581580 | 1615402390,187200 | 119,605620 | 3,394380 | 0,82789753 |
The theoretical duration of this trajectory is 123 seconds. However, motion was completed sooner that expected and also inconsistently across all joints, varying from 0.08 seconds (quite close) to 4.16 seconds (worse case).
I've replicated the drift bug with only ID26 up and running on the network, no SYNC (using default TPDO3 with 30 ms inhibit time), 2000 PT points with period 10 ms (from 50º to -50º at 5º/s): dump.txt. Still getting 19 seconds instead of 20.
Let's take a look at these two consecutive PT points (logged by dumpCanBus --with-ts
):
[1616331605.115300] 26 RPDO3 08 00 00 00 0a 00 00 92
[1616331605.115300] 26 RPDO3 d0 ff ff ff 09 00 00 94
Bytes 4 and 5 should read 0x000a, i.e. 10 samples (time component). As soon as the target position goes negative, the two's complement system wreaks havoc on the most significant bytes coming next, i.e. the 0x000a is turned into 0x0009 (9 samples). That's why the trajectory ended prematurely.
Fixed at https://github.com/roboticslab-uc3m/yarp-devices/commit/a881f95078e45ea74a95875a33e166312f2df472.
Applying a delay in the sending of 25ms (half of the execution period of 50ms by default) between one point and the next, the result is that it performs the execution of the trajectory successfully without any failure.
Along the lines of https://github.com/roboticslab-uc3m/yarp-devices/issues/259, it should not be necessary to apply this hardcoded delay if the remote_controlboard device is configured with --writeStrict on
(cc @rsantos88). Note that the command reader port on the ControlBoardWrapper side is already set as strict, i.e. it should never drop messages, although it will print a "Number of streaming input messages to be read is XXX and can overflow" warning if the buffer size grows rapidly. I believe that this buffer is not limited in size (ref) anyway.
Commit https://github.com/roboticslab-uc3m/yarp-devices/commit/e8d69d3b69e3aae65f7ce6f83933bb6e2f8c95b4 increases the threshold for motion start trigger on the internal queue size so that batches in async pt/pvt are as big as possible (not accounting for occasional timer drifts). Now, despite a max HW buffer size of 9 and 7 points for PT and PVT submodes, respectively, the internal queue needs to allocate 10 and 9 points prior to commanding motion start (one extra point in PVT so that the mean velocity can be extrapolated).
I have successfully tested sync/async pt/pvt with base command examplePositionDirect --batch --ipMode pt --speed 2 --posTarget -10 --posdTarget -20 --period 50
: ip-20210327.zip. Also performing nice on longer distances (100º), higher speeds (10º/s) and tighter periods (10 ms).
PS sending a batch of 5000 PT sync points did not cause CBW to print a warning (using --writeStrict on
and launching both client and server on the same machine).
Done and merged at https://github.com/roboticslab-uc3m/yarp-devices/commit/44f2fbc8ca7271cf4e6184ba0e06936f9663319c.
Commit https://github.com/roboticslab-uc3m/yarp-devices/commit/3493779135961acdfb987bbb9a4aa7e656a86659 adds support for async ip and unifies the three currently supported IPositionDirect implementations: CSP, sync PT/PVT, async PT/PVT. A few command-line parameters have been renamed (--pos
, --posd
, --ip
).
Stemming from https://github.com/roboticslab-uc3m/yarp-devices/issues/222, which drops legacy PT/PVT interpolation modes in favor of CSP for online commands (e.g. joystick teleoperation) since the single-element buffer solution was never a good choice anyway, I want to focus on offline usage to actually take advantage of said buffer.
Issues:
Setpoints need to be stored in memory prior to populating the buffer(s): keep in mind it will be pretty easy to overflow the 500-element PCan TX buffer despite having a lower PT/PVT buffer limit (285/222 setpoints, respectively). Those limits do not scale well since there are usually several nodes on the same bus (285 * 6 = ?).
In the same manner, either the CanBusPeak implementation or CAN RW threads of CanBusControlboard should internally manage a queue of messages that exceeds the hardware-limit (500 CAN frames). Currently, it is not allowed (via software) to register more messages into a full queue.
Possible usage:
IRemoteVariables
(https://github.com/roboticslab-uc3m/yarp-devices/issues/222#issuecomment-575095243).IPositionDirect::setPositions
successively in order to save desired setpoints into memory.See https://github.com/roboticslab-uc3m/yarp-devices/issues/198#issuecomment-487279910 regarding PT/PVT buffer size and how to increase it. Default is 9 PT or 7 PVT points.