Tool Libs
UMIT-TIROL Institute of Automation and Control Engineering library collection
 
Loading...
Searching...
No Matches
ODrive.h
Go to the documentation of this file.
1
5#pragma once
6
7#include <cstdio>
8#include <cstring>
9#include <cstdlib>
10#include <core/kern.h>
11
12
14struct ODrive {
15 /* incoming stream */
17 /* outgoing stream */
19 // commands we know about / want to support maybe
20 static constexpr struct {
21 char velocity[15];
22 char current[11];
23 char get[6];
24 char clr[4];
25 } cmds {
26 .velocity = "v %d %.3f %.f\n", // Motor Velocity FeedForward
27 .current = "c %d %.3f\n", // Motor Current
28 .get = "f %d\n", // Motor
29 .clr = "sc\n", // clear errors
30 };
31 enum CMDS { VELO, CURR, GET, CLR };
32 struct Motor; //< forward declaration, needed for REQ
33 struct REQ {
34 enum CMDS cmd;
35 Motor *m; // pointer to requesting motor, used for callback with data
36 Buffer<uint8_t> out; // data to send out
37 };
38 /* queue of pending requests */
39 Queue<REQ> q{8};
40 bool _alive{false};
41 bool alive() {
42 if (_alive && q.full()) { // stopped responding. assume dead
43 _alive = false;
44 // flush pending queue
45 while (!q.empty()) q.pop();
46 }
47 return _alive;
48 }
50 struct Motor {
52 uint8_t side;
53 double pos{0};
54 double vel{0};
56 void setSpeed(double speed) {
57 if (!drive->alive()) {
58 pos = vel = 0;
59 return;
60 }
61 Buffer<uint8_t> cmd = 32;
62 cmd.len = snprintf((char*)cmd.buf, cmd.size, cmds.velocity, side, speed, 0);
63 drive->q.trypush({
64 .cmd = VELO,
65 .m = this,
66 .out = std::move(cmd),
67 });
68 drive->poll();
69 }
71 void measure() {
72 if (!drive->alive()) {
73 pos = vel = 0;
74 return;
75 }
76 Buffer<uint8_t> cmd = 32;
77 cmd.len = snprintf((char*)cmd.buf, cmd.size, cmds.get, side);
78 drive->q.trypush({
79 .cmd = GET,
80 .m = this,
81 .out = std::move(cmd),
82 });
83 drive->poll();
84 }
85 void callback(REQ req, const Buffer<uint8_t> &resp) {
86 assert(req.m == this);
87 if (req.cmd != GET) return; // ignore responses we didn't request
88 char *next = nullptr;
89 pos = strtod((char*)resp.buf, &next);
90 next++; // white space
91 vel = strtod(next, nullptr);
92 }
93 };
95 void poll() {
96 if (!_alive) {
97 if (!in.empty()) {
98 auto resp = in.pop();
99 double volt = strtod((char*)resp.buf, nullptr);
100 if (23. < volt && volt < 25.) {
101 _alive = true;
102 }
103 } else if (k.time % 500 == 0) {
104 out.trypush({(const uint8_t*)"r vbus_voltage\n", 16});
105 }
106 return;
107 }
108 while (!in.empty()) {
109 assert(!q.empty()); // can't receive things without requesting them first
110 auto resp = in.pop();
111 auto req = q.pop();
112 req.m->callback(req, resp);
113 }
114 while (!q.empty() && q.front().out.buf) { // command has not been sent
115 out.trypush(std::move(q.front().out));
116 if (q.front().cmd != GET) { // only expect response from GET
117 q.pop();
118 }
119 }
120 }
121};
const uint32_t & time
const access to global uptime
Definition kern.h:30
simple Buffer backed queue implementation
Definition queue.h:12
T pop() override
remove front of queue and return it
Definition queue.h:65
bool empty() override
check if queue is empty
Definition queue.h:83
bool full() override
return true if queue is full
Definition queue.h:87
T & front()
return reference to first element in queue
Definition queue.h:55
Copyright (c) 2023 IACE.
dynamically allocated, but fixed-size buffer template
Definition buffer.h:18
size_t size
total capacity of buffer
Definition buffer.h:23
size_t len
number of items stored in buffer
Definition buffer.h:21
single motor controlled by the ODrive interface
Definition ODrive.h:50
double pos
last measured position
Definition ODrive.h:53
void measure()
get new measurements from motor
Definition ODrive.h:71
void setSpeed(double speed)
set speed in rot/s
Definition ODrive.h:56
ODrive * drive
pointer to controlling ODrive
Definition ODrive.h:51
double vel
last measured velocity [rot/s]
Definition ODrive.h:54
uint8_t side
the ODrive hardware supports 2 Motors
Definition ODrive.h:52
support for the odriverobotics.com v3 Motor Driver UART interface
Definition ODrive.h:14
void poll()
call this regularly to check for updates
Definition ODrive.h:95
generic object sink, i.e.
Definition streams.h:15
void trypush(T &&t)
use this if you don't care if it's going to be successful. data gets discarded if sink is full.
Definition streams.h:28
generic object source, i.e.
Definition streams.h:40
virtual T pop()=0
pull object from source does not check for data. guard by using 'if (!empty) { ......
virtual bool empty()=0
check if source is empty