Skip to content

Commit f1da7e2

Browse files
Update and add CAN, VESC, MELM.
Co-authored-by: James Goppert <james.goppert@gmail.com> Signed-off-by: Benjamin Perseghetti <bperseghetti@rudislabs.com>
1 parent 0b47d06 commit f1da7e2

File tree

6 files changed

+106
-33
lines changed

6 files changed

+106
-33
lines changed

app/melm/Kconfig

+2-2
Original file line numberDiff line numberDiff line change
@@ -90,13 +90,13 @@ config CEREBRI_MELM_GAIN_ALONG_TRACK
9090

9191
config CEREBRI_MELM_MAX_VELOCITY_MM_S
9292
int "max velocity, mm/s"
93-
default 2000
93+
default 200
9494
help
9595
Max velocity in mm/s
9696

9797
config CEREBRI_MELM_WHEEL_RADIUS_MM
9898
int "wheel radius, mm"
99-
default 108
99+
default 104
100100
help
101101
Wheel radius in mm
102102

app/melm/boards/mr_canhubk3_s32k344.conf

+2-1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ CONFIG_LOG_MODE_DEFERRED=y
2525
CONFIG_LOG_MODE_IMMEDIATE=n
2626

2727
CONFIG_FPU=y
28+
CONFIG_PWM=y
2829

2930
# config
3031
CONFIG_INPUT=y
@@ -41,7 +42,7 @@ CONFIG_INPUT_THREAD_STACK_SIZE=2048
4142
CONFIG_CEREBRI_SENSE_SBUS=y
4243
CONFIG_CEREBRI_SENSE_IMU=y
4344
CONFIG_CEREBRI_SENSE_MAG=y
44-
CONFIG_CEREBRI_SENSE_SAFETY=n
45+
CONFIG_CEREBRI_SENSE_SAFETY=y
4546
CONFIG_CEREBRI_SENSE_UBX_GNSS=y
4647

4748
CONFIG_CEREBRI_SYNAPSE_ETH_RX=y

app/melm/boards/mr_canhubk3_s32k344.overlay

+2
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
vesc_can_actuators: vesc_can_actuators {
1212
compatible = "cerebri,vesc_can-actuators";
1313
device = <&flexcan0>;
14+
pub-wheel-odometry;
15+
status-rate = <50>;
1416
motor0 {
1517
vesc-id = <60>;
1618
input-type = "velocity";

app/melm/prj.conf

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ CONFIG_CEREBRI_SENSE_POWER=y
2727
CONFIG_CEREBRI_SENSE_SAFETY=y
2828
CONFIG_CEREBRI_SENSE_IMU=y
2929
CONFIG_CEREBRI_SENSE_MAG=y
30-
CONFIG_CEREBRI_SENSE_WHEEL_ODOMETRY=y
30+
CONFIG_CEREBRI_SENSE_WHEEL_ODOMETRY=n
3131
CONFIG_CEREBRI_SENSE_UBX_GNSS=y
3232

3333
CONFIG_CEREBRI_SYNAPSE_ETH_RX=y

drivers/actuate/vesc_can/main.c

+90-29
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ LOG_MODULE_REGISTER(actuate_vesc_can, CONFIG_CEREBRI_ACTUATE_VESC_CAN_LOG_LEVEL)
3131
#define MY_STACK_SIZE 4096
3232
#define MY_PRIORITY 4
3333

34+
#define CAN_STATUS_ID_BASE 0x00000900
35+
3436
#ifndef M_PI
3537
#define M_PI 3.14159265358979323846
3638
#endif
@@ -39,46 +41,70 @@ uint32_t g_send_count = 0;
3941

4042
extern struct perf_duration control_latency;
4143

44+
static void actuate_vesc_can_rx_callback(const struct device *dev, struct can_frame *frame,
45+
void *user_data);
46+
4247
typedef enum vesc_can_type_t {
4348
VESC_CAN_TYPE_NORMALIZED = 0,
4449
VESC_CAN_TYPE_POSITION = 1,
4550
VESC_CAN_TYPE_VELOCITY = 2,
4651
} vesc_can_type_t;
4752

48-
typedef struct actuator_vesc_can_t {
53+
struct actuator_vesc_can {
4954
const char *label;
5055
uint8_t id;
5156
uint8_t index;
5257
uint8_t pole_pair;
5358
uint8_t vesc_id;
5459
vesc_can_type_t type;
55-
} actuator_vesc_can_t;
60+
struct can_filter rx_filter;
61+
struct context *ctx;
62+
double rotation;
63+
};
5664

5765
struct context {
5866
synapse_pb_Actuators actuators;
67+
synapse_pb_WheelOdometry wheel_odometry;
5968
synapse_pb_Status status;
6069
struct zros_node node;
6170
struct zros_sub sub_actuators, sub_status;
71+
struct zros_pub pub_wheel_odometry;
6272
struct k_sem running;
6373
size_t stack_size;
6474
k_thread_stack_t *stack_area;
6575
struct k_thread thread_data;
6676
uint8_t num_actuators;
67-
actuator_vesc_can_t *actuator_vesc_cans;
77+
struct actuator_vesc_can *actuator_vesc_cans;
6878
const struct device *device;
6979
bool ready;
7080
bool fd;
7181
const char *label;
82+
uint16_t status_rate;
83+
bool enable_pub_wheel_odom;
7284
};
7385

7486
static int actuate_vesc_can_stop(struct context *ctx)
7587
{
88+
int err = 0;
89+
struct can_bus_err_cnt err_cnt;
90+
enum can_state state;
7691
ctx->ready = false;
77-
int err = can_stop(ctx->device);
92+
err = can_get_state(ctx->device, &state, &err_cnt);
7893
if (err != 0) {
79-
LOG_ERR("%s - failed to stop (%d)\n", ctx->label, err);
94+
LOG_ERR("%s - failed to get CAN controller state (%d)\n", ctx->label, err);
95+
ctx->ready = false;
8096
return err;
8197
}
98+
99+
// make sure stopped
100+
if (state != CAN_STATE_STOPPED) {
101+
err = can_stop(ctx->device);
102+
if (err != 0) {
103+
LOG_ERR("%s - failed to stop (%d)\n", ctx->label, err);
104+
return err;
105+
}
106+
}
107+
82108
return err;
83109
}
84110

@@ -88,9 +114,8 @@ static int actuate_vesc_can_init(struct context *ctx)
88114
zros_node_init(&ctx->node, "actuate_vesc_can");
89115
zros_sub_init(&ctx->sub_actuators, &ctx->node, &topic_actuators, &ctx->actuators, 1000);
90116
zros_sub_init(&ctx->sub_status, &ctx->node, &topic_status, &ctx->status, 10);
91-
92-
enum can_state state;
93-
struct can_bus_err_cnt err_cnt;
117+
zros_pub_init(&ctx->pub_wheel_odometry, &ctx->node, &topic_wheel_odometry,
118+
&ctx->wheel_odometry);
94119

95120
if (ctx->ready) {
96121
LOG_ERR("%s - already initialized", ctx->label);
@@ -102,19 +127,12 @@ static int actuate_vesc_can_init(struct context *ctx)
102127
LOG_ERR("%s - device not ready\n", ctx->label);
103128
ctx->ready = false;
104129
return -1;
105-
} // check state
106-
err = can_get_state(ctx->device, &state, &err_cnt);
107-
if (err != 0) {
108-
LOG_ERR("%s - failed to get CAN controller state (%d)\n", ctx->label, err);
109-
ctx->ready = false;
110-
return err;
111130
}
112131

132+
actuate_vesc_can_stop(ctx);
133+
113134
// set device mode
114135
if (ctx->fd) {
115-
if (state != CAN_STATE_STOPPED) {
116-
actuate_vesc_can_stop(ctx);
117-
}
118136
err = can_set_mode(ctx->device, CAN_MODE_FD);
119137
if (err != 0) {
120138
LOG_ERR("%s - set mode FD failed (%d)\n", ctx->label, err);
@@ -123,10 +141,23 @@ static int actuate_vesc_can_init(struct context *ctx)
123141
}
124142

125143
// start device
126-
if ((state == CAN_STATE_STOPPED) || (state == CAN_STATE_BUS_OFF)) {
127-
err = can_start(ctx->device);
128-
if (err != 0) {
129-
LOG_ERR("%s - start failed\n", ctx->label);
144+
err = can_start(ctx->device);
145+
if (err != 0) {
146+
LOG_ERR("%s - start failed\n", ctx->label);
147+
return err;
148+
}
149+
150+
// add receive callback
151+
for (int i = 0; i < ctx->num_actuators; i++) {
152+
struct actuator_vesc_can *act = &ctx->actuator_vesc_cans[i];
153+
act->ctx = ctx;
154+
act->rx_filter.flags = CAN_FILTER_IDE;
155+
act->rx_filter.id = CAN_STATUS_ID_BASE + act->vesc_id;
156+
act->rx_filter.mask = CAN_EXT_ID_MASK;
157+
err = can_add_rx_filter(ctx->device, actuate_vesc_can_rx_callback, act,
158+
&act->rx_filter);
159+
if (err < 0) {
160+
LOG_ERR("%s - callback setup failed (%d)\n", ctx->label, err);
130161
return err;
131162
}
132163
}
@@ -143,32 +174,55 @@ static int actuate_vesc_can_fini(struct context *ctx)
143174
actuate_vesc_can_stop(ctx);
144175
zros_sub_fini(&ctx->sub_actuators);
145176
zros_sub_fini(&ctx->sub_status);
177+
zros_pub_fini(&ctx->pub_wheel_odometry);
146178
zros_node_fini(&ctx->node);
147179
k_sem_give(&ctx->running);
148180
LOG_INF("fini");
149181
return 0;
150182
}
151183

184+
static void actuate_vesc_can_rx_callback(const struct device *dev, struct can_frame *frame,
185+
void *user_data)
186+
{
187+
struct actuator_vesc_can *act = (struct actuator_vesc_can *)user_data;
188+
struct context *ctx = act->ctx;
189+
int64_t data = (frame->data[0] << 24) + (frame->data[1] << 16) + (frame->data[2] << 8) +
190+
frame->data[3];
191+
act->rotation += 2 * M_PI * data / (act->pole_pair * ctx->status_rate * 60);
192+
// LOG_INF("Data: %ld", data);
193+
// LOG_INF("Angular: %f", act->rotation);
194+
if (act->id == ctx->actuator_vesc_cans[0].id) {
195+
double mean_rotation = 0;
196+
for (int i = 0; i < ctx->num_actuators; i++) {
197+
mean_rotation += ctx->actuator_vesc_cans[i].rotation;
198+
}
199+
mean_rotation /= ctx->num_actuators;
200+
ctx->wheel_odometry.has_stamp = true;
201+
stamp_msg(&ctx->wheel_odometry.stamp, k_uptime_ticks());
202+
ctx->wheel_odometry.rotation = mean_rotation;
203+
}
204+
}
205+
152206
static void actuate_vesc_can_update(struct context *ctx)
153207
{
154208
bool armed = ctx->status.arming == synapse_pb_Status_Arming_ARMING_ARMED;
155209
int err = 0;
156210

157211
for (int i = 0; i < ctx->num_actuators; i++) {
158-
actuator_vesc_can_t *vesc_can = &ctx->actuator_vesc_cans[i];
212+
struct actuator_vesc_can *act = &ctx->actuator_vesc_cans[i];
159213

160214
struct can_frame frame = {
161215
.dlc = can_bytes_to_dlc(4),
162216
.flags = CAN_FRAME_IDE,
163217
};
164218
double input = 0;
165219

166-
if (vesc_can->type == VESC_CAN_TYPE_VELOCITY && armed) {
167-
input = ctx->actuators.velocity[vesc_can->index];
220+
if (act->type == VESC_CAN_TYPE_VELOCITY && armed) {
221+
input = ctx->actuators.velocity[act->index];
168222
}
169223

170-
int32_t erpm = vesc_can->pole_pair * input * 60 / (2 * M_PI);
171-
frame.id = 768 + vesc_can->vesc_id;
224+
int32_t erpm = act->pole_pair * input * 60 / (2 * M_PI);
225+
frame.id = 768 + act->vesc_id;
172226
frame.data[0] = erpm >> 24 & 255;
173227
frame.data[1] = erpm >> 16 & 255;
174228
frame.data[2] = erpm >> 8 & 255;
@@ -179,8 +233,8 @@ static void actuate_vesc_can_update(struct context *ctx)
179233
err = can_send(ctx->device, &frame, K_NO_WAIT, NULL, NULL);
180234
if (err != 0) {
181235
ctx->ready = false;
182-
LOG_ERR("%s - send failed to VESC ID: %d (%d)\n", vesc_can->label,
183-
vesc_can->vesc_id, err);
236+
LOG_ERR("%s - send failed to VESC ID: %d (%d)\n", act->label, act->vesc_id,
237+
err);
184238
continue;
185239
}
186240
perf_duration_stop(&control_latency);
@@ -224,6 +278,8 @@ static void actuate_vesc_can_run(void *p0, void *p1, void *p2)
224278
zros_sub_update(&ctx->sub_actuators);
225279
}
226280

281+
zros_pub_update(&ctx->pub_wheel_odometry);
282+
227283
// update vesc_can
228284
actuate_vesc_can_update(ctx);
229285
}
@@ -290,10 +346,13 @@ static int actuate_vesc_can_device_init(const struct device *dev)
290346
.pole_pair = DT_PROP(node_id, pole_pair), \
291347
.vesc_id = DT_PROP(node_id, vesc_id), \
292348
.type = DT_ENUM_IDX(node_id, input_type), \
349+
.rx_filter = {}, \
350+
.ctx = NULL, \
351+
.rotation = 0, \
293352
},
294353

295354
#define VESC_CAN_ACTUATORS_DEFINE(inst) \
296-
static actuator_vesc_can_t g_actuator_vesc_cans_##inst[] = { \
355+
static struct actuator_vesc_can g_actuator_vesc_cans_##inst[] = { \
297356
DT_FOREACH_CHILD(DT_DRV_INST(inst), VESC_CAN_ACTUATOR_DEFINE)}; \
298357
static K_THREAD_STACK_DEFINE(g_my_stack_area_##inst, MY_STACK_SIZE); \
299358
static struct context data_##inst = { \
@@ -311,6 +370,8 @@ static int actuate_vesc_can_device_init(const struct device *dev)
311370
.device = DEVICE_DT_GET(DT_INST_PROP(inst, device)), \
312371
.ready = false, \
313372
.fd = DT_INST_PROP(inst, fd), \
373+
.status_rate = DT_INST_PROP(inst, status_rate), \
374+
.enable_pub_wheel_odom = DT_INST_PROP(inst, pub_wheel_odometry), \
314375
.label = DT_NODE_FULL_NAME(DT_DRV_INST(inst)), \
315376
}; \
316377
VESC_CAN_ACTUATOR_SHELL(inst); \

dts/bindings/cerebri,vesc_can-actuators.yaml

+9
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,15 @@ properties:
1818
type: boolean
1919
description: enable CAN FD mode
2020

21+
pub-wheel-odometry:
22+
type: boolean
23+
description: Publishes wheel odometry on the average of all wheels
24+
25+
status-rate:
26+
required: true
27+
type: int
28+
description: vesc can status publication rate in Hz. If status-rate <0> disables.
29+
2130
child-binding:
2231
description: VESC_CAN actuators node
2332
properties:

0 commit comments

Comments
 (0)