Haptic Controller
Loading...
Searching...
No Matches
odrive_controller.hpp
Go to the documentation of this file.
1#pragma once
2#include <Arduino.h>
3#include "ODriveCAN.h"
4#include <FlexCAN_T4.h>
5#include "ODriveFlexCAN.hpp"
6#include "teensy_can.h"
7#include "defines.h"
10#include "utils/helpers.hpp"
11
14template<CAN_DEV_TABLE CAN>
16{
17public:
18 OdriveController() = default;
19 ~OdriveController() = default;
20
26 FlexCAN_T4<CAN, RX_SIZE_256, TX_SIZE_256> & odrive_can,
27 int CAN_ID,
28 ODriveUserData & odrv_user_data)
29 : odrive_can_(odrive_can),
30 odrv_(ODriveCAN(wrap_can_intf(odrive_can), CAN_ID)),
31 odrv_user_data_(odrv_user_data)
32 {
33 odrv_user_data_.node_id = CAN_ID;
34 // Register callbacks for the heartbeat and encoder feedback messages
35 odrv_.onFeedback(onFeedback, &odrv_user_data_);
37 odrv_.onTemperature(onTemperature, &odrv_user_data_);
38 }
40 FlexCAN_T4<CAN, RX_SIZE_256, TX_SIZE_256> & odrive_can_;
41
43 ODriveCAN odrv_;
44
47
50
51 float alpha_ = 0.95; // This is the percentage of the joint limit before we begin limiting the outputted torque
52
55 {
56 Serial.println("Setting parameters: ");
58 for (u_int i = 0; i < fconfig_params.size(); i++) {
59 param.Endpoint_ID = fconfig_params[i].endpoint_id;
60 param.Value = fconfig_params[i].value;
61
62 Serial.print("Setting param: ");
63 Serial.println(param.Endpoint_ID);
64 odrv_.send(param);
65 pumpEvents(odrive_can_);
66 delay(100);
67 }
68
70 for (u_int i = 0; i < bconfig_params.size(); i++) {
71 bparam.Endpoint_ID = bconfig_params[i].endpoint_id;
72 bparam.Value = bconfig_params[i].value;
73 Serial.print("Setting param: ");
74 Serial.println(bparam.Endpoint_ID);
75 odrv_.send(bparam);
76 pumpEvents(odrive_can_);
77 delay(100);
78 }
79
80 return true;
81 }
82
85 {
86 Serial.println("Starting Calibration");
87 odrv_.setState(ODriveAxisState::AXIS_STATE_FULL_CALIBRATION_SEQUENCE);
88 delay(1000);
89 Serial.println("Calibration Done!");
90 return true;
91 }
92
95 {
96 odrv_.setControllerMode(
97 ODriveControlMode::CONTROL_MODE_POSITION_CONTROL,
98 ODriveInputMode::INPUT_MODE_PASSTHROUGH);
99 odrv_.setState(ODriveAxisState::AXIS_STATE_CLOSED_LOOP_CONTROL);
100 Serial.println("Moving to upper limit.");
101 odrv_.setPosition(motor_limits_.upper);
102 delay(1000);
103 Serial.println("Moving to lower limit.");
104 odrv_.setPosition(motor_limits_.lower);
105 delay(1000);
106 Serial.println("Done Checking Limits");
107 odrv_.setControllerMode(
108 ODriveControlMode::CONTROL_MODE_TORQUE_CONTROL,
109 ODriveInputMode::INPUT_MODE_PASSTHROUGH);
110 return true;
111 }
112
115 bool enable_anticogging(bool doCalibration = false)
116 {
117 Serial.println("Attempting to turn on anticogging");
119 for (u_int i = 0; i < fanticogging_config_params.size(); i++) {
120 fparam.Endpoint_ID = fanticogging_config_params[i].endpoint_id;
121 fparam.Value = fanticogging_config_params[i].value;
122
123 Serial.print("Setting param: ");
124 Serial.println(fparam.Endpoint_ID);
125 odrv_.send(fparam);
126 pumpEvents(odrive_can_);
127 delay(100);
128 }
129
131 for (u_int i = 0; i < banticogging_config_params.size(); i++) {
132 bparam.Endpoint_ID = banticogging_config_params[i].endpoint_id;
133 bparam.Value = banticogging_config_params[i].value;
134
135 Serial.print("Setting param: ");
136 Serial.println(bparam.Endpoint_ID);
137 odrv_.send(bparam);
138 pumpEvents(odrive_can_);
139 delay(100);
140 }
141 Serial.println("Successfully set anticogging configuration");
142
143 if (doCalibration) {
144 odrv_.setState(ODriveAxisState::AXIS_STATE_ANTICOGGING_CALIBRATION);
145 delay(1000);
146 Serial.println("Starting anticogging calibration");
147 // Check if done
148 delay(480 * 1000);
149 Serial.println("Finished anticogging calibration");
150 }
151
152 bparam.Endpoint_ID = benable_config_param.endpoint_id;
153 bparam.Value = benable_config_param.value;
154 Serial.print("Setting param: ");
155 Serial.println(bparam.Endpoint_ID);
156 odrv_.send(bparam);
157 pumpEvents(odrive_can_);
158 delay(100);
159 Serial.println("Enabled anticogging");
160
161 Set_Reboot_msg_t reboot;
162 reboot.Action = 1;
163 odrv_.send(reboot);
164 delay(10 * 1000);
165 Serial.println("Reboot successful");
166 return true;
167 }
168
171 {
172 Serial.println("\nAttempting to set configuration and start torque mode!");
173
174 set_params();
175 Serial.println("Configuration set");
176
177 Serial.println("Checking Temperature...");
178
179 odrv_.setControllerMode(
180 ODriveControlMode::CONTROL_MODE_TORQUE_CONTROL,
181 ODriveInputMode::INPUT_MODE_PASSTHROUGH);
182 Serial.println("Setting to Torque mode");
183
184 return true;
185 }
186
190 void set_torque(float torque)
191 {
192 const auto pos = odrv_user_data_.last_feedback.Pos_Estimate;
193
194 // The position is outside of the joint limits
196 odrv_.setTorque(0);
197 return;
198 }
199
200 // Here the joint limits are with in the acceptable range. No throttling required
202 odrv_.setTorque(torque);
203 return;
204 }
205
206 // If we are in the upper buffer
207 if (pos >= motor_limits_.upper * alpha_) {
208 const auto gain = (motor_limits_.upper - pos) / motor_limits_.upper;
209 odrv_.setTorque(torque * gain);
210 return;
211 }
212
213 // Only other condition is if we are in the lower buffer
214 const auto gain = (motor_limits_.lower - pos) / motor_limits_.lower;
215 odrv_.setTorque(torque * gain);
216 return;
217 }
218};
Class that abstracts operations with the ODrive/.
bool move_to_limits()
Move to the upper and lower limits of the joint.
OdriveController(FlexCAN_T4< CAN, RX_SIZE_256, TX_SIZE_256 > &odrive_can, int CAN_ID, ODriveUserData &odrv_user_data)
Constructor for the ODriveController.
Limits< float > motor_limits_
: Limits on motor torques
ODriveUserData & odrv_user_data_
struct to store user data in
bool startup_odrive_checks()
Set parameters and set the motor to torque control.
void set_torque(float torque)
Function to set the torque values based on the joint limits recorded from the startup_calibration.
bool set_params()
Set parameters on the ODrive.
FlexCAN_T4< CAN, RX_SIZE_256, TX_SIZE_256 > & odrive_can_
Address of canline for this odrive.
bool full_calibration()
Run the full calibration sequence given by ODrive.
ODriveCAN odrv_
Odrive object to control.
OdriveController()=default
bool enable_anticogging(bool doCalibration=false)
Set parameters for anticogging and enable it.
~OdriveController()=default
std::vector< float > pos
Definition main.cpp:72
void onTemperature(Get_Temperature_msg_t &msg, void *user_data)
: Called every time a temperature message arrives from the ODrive
void onFeedback(Get_Encoder_Estimates_msg_t &msg, void *user_data)
: Called every time a feedback message arrives from the ODrive
void onHeartbeat(Heartbeat_msg_t &msg, void *user_data)
: Called every time a heartbeat message arrives from the ODrive
auto benable_config_param
std::vector< Param< float > > fanticogging_config_params({Param< float >{"spinout_mechanical_power_threshold", 420, -100.0}, Param< float >{"spinout_eletrical_power_threshold", 421, 100.0}, Param< float >{"max_regen_current", 139, 50.0}, Param< float >{"dc_max_negative_current", 143, -50.0}, Param< float >{"pos_gain", 400, 20.0}, Param< float >{"vel_gain", 401, 8.5e-3}, Param< float >{"vel_integrator_gain", 402, 0.0}, Param< float >{"torque_soft_min", 267, -150.0}, Param< float >{"torque_soft_max", 268, 150.0}, Param< float >{"anticogging.max_torque", 305, 0.15}, Param< float >{"anticogging.calib_start_vel", 306, 1}, Param< float >{"anticogging.calib_end_val", 307, 0.15}, Param< float >{"anticogging.calib_coarse_integrator_gain", 311, 1}})
std::vector< Param< float > > fconfig_params({ Param< float >{"spinout_mechanical_power_threshold", 420, -100.0}, Param< float >{"spinout_eletrical_power_threshold", 421, 100.0}, Param< float >{"max_regen_current", 139, 50.0}, Param< float >{"dc_max_negative_current", 143, -50.0}, Param< float >{"pos_gain", 400, 100}, Param< float >{"vel_gain", 401, 12}, Param< float >{"vel_integrator_gain", 402, 0.0}, Param< float >{"torque_soft_min", 267, -10.0}, Param< float >{"torque_soft_max", 268, 10.0}, Param< float >{"calib_scan_dist", 215, 4.0}, Param< float >{"motor_thermistor.config.r_ref", 352, 10000}, Param< float >{"motor_thermistor.config.t_ref", 353, 25}, Param< float >{"motor_thermistor.config.beta", 354, 3892}, Param< float >{"motor_thermistor.config.temp_limit_lower", 355, 60}, Param< float >{"motor_thermistor.config.temp_limit_upper", 356, 90}, Param< float >{"vel_limit", 404, 30.0}, Param< float >{"vel_limit_tolerance", 405, 1.5}, })
std::vector< Param< uint32_t > > bconfig_params({ Param< uint32_t >{"version_msg_rate_ms", 248, 0}, Param< uint32_t >{"iq_msg_rate_ms", 251, 0}, Param< uint32_t >{"bus_voltage_msg_rate_ms", 254, 0}, Param< uint32_t >{"powers_msg_rate_ms", 256, 0}, Param< uint32_t >{"gpio7_mode", 159, 3}, Param< uint32_t >{"motor_thermistor.config.enabled", 357, 0}, Param< uint32_t >{"can.temperature_msg_rate_ms", 253, 100}, Param< uint32_t >{"enable_vel_limit", 393, 1}, Param< uint32_t >{"enable_torque_mode_vel_limit", 394, 1}, })
std::vector< Param< uint32_t > > banticogging_config_params({Param< uint32_t >{"circular_setpoints", 408, true}, Param< uint32_t >{"offset_valid", 466, true}})
Limit struct to store upper and lower limits.
Definition helpers.hpp:34
T upper
Definition helpers.hpp:36
T lower
Definition helpers.hpp:35
: The Struct to contain feedback from the ODrive
Get_Encoder_Estimates_msg_t last_feedback
Structure for setting ODrive Parameters Endpoint_ids can be found at the following link: https://odri...
uint16_t Endpoint_ID
Message struct for reboooting Odrive.