Hello,
I have a ServoTarget.pb.h which contains the following:
/* Automatically generated nanopb header */
/* Generated by nanopb-0.4.8-dev */
#ifndef PB_MESSAGE_ACTUATION_SERVOTARGET_PB_H_INCLUDED
#define PB_MESSAGE_ACTUATION_SERVOTARGET_PB_H_INCLUDED
#include "pb.h"
#include "timestamp.pb.h"
#if PB_PROTO_HEADER_VERSION != 40
#error Regenerate this file with the current version of nanopb generator.
#endif
typedef struct _message_actuation_ServoTarget {
/* / When the target was created */
bool has_time;
google_protobuf_Timestamp time;
/* / The ID of the servo being controlled */
uint32_t id;
/* / The position value of the destination. 0 to 4,095 (0xFFF) is available.
/ The unit is 0.088 [°]. If Goal Position is out of the range, Angle Limit
/ Error Bit (Bit1) of Status Packet is returned as ‘1’ and Alarm is
/ triggered as set in Alarm LED/Shutdown */
float position;
/* / Proportional gain. In proportion to the servo's position error. Gain
/ values are in range 0~254. K_p : p_gain / 8 */
float gain;
/* / Used to set the servo on or off. Typically either 0 (off) or 100 (on) */
float torque;
} message_actuation_ServoTarget;
typedef struct _message_actuation_ServoTargets {
pb_callback_t targets;
} message_actuation_ServoTargets;
#ifdef __cplusplus
extern "C" {
#endif
/* Initializer values for message structs */
#define message_actuation_ServoTarget_init_default {false, google_protobuf_Timestamp_init_default, 0, 0, 0, 0}
#define message_actuation_ServoTargets_init_default {{{NULL}, NULL}}
#define message_actuation_ServoTarget_init_zero {false, google_protobuf_Timestamp_init_zero, 0, 0, 0, 0}
#define message_actuation_ServoTargets_init_zero {{{NULL}, NULL}}
/* Field tags (for use in manual encoding/decoding) */
#define message_actuation_ServoTarget_time_tag 1
#define message_actuation_ServoTarget_id_tag 2
#define message_actuation_ServoTarget_position_tag 3
#define message_actuation_ServoTarget_gain_tag 4
#define message_actuation_ServoTarget_torque_tag 5
#define message_actuation_ServoTargets_targets_tag 1
/* Struct field encoding specification for nanopb */
#define message_actuation_ServoTarget_FIELDLIST(X, a) \
X(a, STATIC, OPTIONAL, MESSAGE, time, 1) \
X(a, STATIC, SINGULAR, UINT32, id, 2) \
X(a, STATIC, SINGULAR, FLOAT, position, 3) \
X(a, STATIC, SINGULAR, FLOAT, gain, 4) \
X(a, STATIC, SINGULAR, FLOAT, torque, 5)
#define message_actuation_ServoTarget_CALLBACK NULL
#define message_actuation_ServoTarget_DEFAULT NULL
#define message_actuation_ServoTarget_time_MSGTYPE google_protobuf_Timestamp
#define message_actuation_ServoTargets_FIELDLIST(X, a) \
X(a, CALLBACK, REPEATED, MESSAGE, targets, 1)
#define message_actuation_ServoTargets_CALLBACK pb_default_field_callback
#define message_actuation_ServoTargets_DEFAULT NULL
#define message_actuation_ServoTargets_targets_MSGTYPE message_actuation_ServoTarget
extern const pb_msgdesc_t message_actuation_ServoTarget_msg;
extern const pb_msgdesc_t message_actuation_ServoTargets_msg;
/* Defines for backwards compatibility with code written before nanopb-0.4.0 */
#define message_actuation_ServoTarget_fields &message_actuation_ServoTarget_msg
#define message_actuation_ServoTargets_fields &message_actuation_ServoTargets_msg
/* Maximum encoded size of messages (where known) */
/* message_actuation_ServoTargets_size depends on runtime parameters */
#define message_actuation_ServoTarget_size 45
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif
And I have provided the following callback function and structs:
typedef struct ServoTarget {
uint8_t id;
float position;
float gain;
float torque;
};
typedef struct ServoTargets {
ServoTarget targets[20];
size_t idx;
};
void nanopb_decode_callback(pb_istream_t *stream, const pb_field_t *field, void *arg) {
ServoTargets *servo_targets = (ServoTargets *)arg;
ServoTarget target;
if (!pb_decode(stream, message_actuation_ServoTarget_fields, &target)) {
// Decoding failed
return false;
}
if (servo_targets->idx < 20) {
servo_targets->targets[servo_targets->idx++] = target;
}
else {
// Expected repeated field size exceeded
return false;
}
return true;
}
How do I set this as the decode callback function? Would it be like so?
// Decoding time
pb_istream_t input_stream = pb_istream_from_buffer(reinterpret_cast<const pb_byte_t*>(&pb_packets[0]), rx_buf_len - rx_buf_idx);
// Instance of ServoTargets to store the decoded messages
ServoTargets servo_targets_message = {0};
// Set up the callback to handle decoding of the repeated field
message_actuation_ServoTargets_msg.fields[0].cb_funcs.decode = &nanopb_decode_callback;
message_actuation_ServoTargets_msg.fields[0].ptr = &servo_targets_message;
Then accessing it like so, using the servo_targets_message struct:
// Iterate over the decoded ServoTarget messages
for (size_t i = 0; i < 20; i++) {
ServoTarget *target = &servo_targets_message.targets[i];
// Access fields of the individual ServoTarget message
printf("ServoTarget %zu: ID=%lu, Position=%.2f, Gain=%.2f, Torque=%.2f\n",
i + 1, target->id, target->position, target->gain, target->torque);
}
Is this in the right track? I have been trying to look at the docs (If there was some info that I could not find, I apologise in advance) and how other people did it with similar messages like mine, but I just could not find the cb_funcs.decode field nor the ptr field for message_actuation_ServoTargets_msg.fields[0] in any of the generated files, hence the skepticism.
Thank you very much in advance, and merry Christmas!\