TinyRobotics
Loading...
Searching...
No Matches
Quadrotor.h
1
2#pragma once
3
4#include "TinyRobotics/motors/Motors.h"
5#include "Vehicle.h"
6
7namespace tinyrobotics {
8
9/// @brief Enum for quadrotor motor indexing
10enum QuadrotorMotorNo {
11 FRONT_LEFT = 0,
12 FRONT_RIGHT = 1,
13 REAR_LEFT = 2,
14 REAR_RIGHT = 3
15};
16
17/**
18 * @class Quadrotor
19 * @ingroup vehicles
20 * @brief Simple quadrotor (quadcopter) model with 4-motor control.
21 *
22 * This class abstracts the control of a basic quadcopter:
23 * - 4 motors (front left, front right, rear left, rear right) via HBridge
24 * - Throttle, roll, pitch, and yaw control
25 *
26 * Usage Example (with setPins):
27 * @code
28 * Quadrotor quad;
29 * quad.setPins(FRONT_LEFT, m1_in1, m1_in2); // front left
30 * quad.setPins(FRONT_RIGHT, m2_in1, m2_in2); // front right
31 * quad.setPins(REAR_LEFT, m3_in1, m3_in2); // rear left
32 * quad.setPins(REAR_RIGHT, m4_in1, m4_in2); // rear right
33 * quad.setThrottle(60); // 60% throttle
34 * quad.setRoll(10); // roll right
35 * quad.setPitch(-5); // pitch down
36 * quad.setYaw(15); // yaw right
37 * @endcode
38 */
39
40template <typename T=float, typename DriverT = BrushedMotor<T>>
41class Quadrotor : public Vehicle<T> {
42 public:
43 Quadrotor() = default;
44
45 /**
46 * @brief Set the pins for a specific motor (0=front left, 1=front right,
47 * 2=rear left, 3=rear right)
48 */
49 void setPins(QuadrotorMotorNo motor, int in1, int in2) {
50 motors_[motor].setPins(in1, in2);
51 motors_[motor].setID((uint8_t)motor);
52 }
53
54 /** Set throttle (0-100%) for all motors */
55 void setThrottle(float percent) {
56 throttle_ = constrain(percent, 0.0f, 100.0f);
58 }
59
60 /** Set roll (-100 to 100): positive = right, negative = left */
61 void setRoll(float percent) {
62 roll_ = constrain(percent, -100.0f, 100.0f);
64 }
65
66 /** Set pitch (-100 to 100): positive = forward, negative = backward */
67 void setPitch(float percent) {
68 pitch_ = constrain(percent, -100.0f, 100.0f);
70 }
71
72 /** Set yaw (-100 to 100): positive = right, negative = left */
73 void setYaw(float percent) {
74 yaw_ = constrain(percent, -100.0f, 100.0f);
76 }
77
78 /** Stop all motors and reset state */
79 void end() override {
81 setRoll(0);
83 setYaw(0);
84 // stop all motors
85 for (auto& motor : getMotors()) {
86 motor.end();
87 }
88 }
89
90 /**
91 * @brief Set a calibration gain for a specific motor (default 1.0).
92 * @param motor Motor index (QuadrotorMotorNo)
93 * @param gain Gain factor (e.g., 1.05 for +5% output)
94 */
95 void setMotorGain(QuadrotorMotorNo motor, float gain) {
96 motorGain_[motor] = gain;
97 }
98
99 bool isPinsSet() const {
100 for (int i = 0; i < 4; ++i) {
101 if (!motors_[i].isPinsSet()) return false;
102 }
103 return true;
104 }
105
106 bool onMessage(const Message<float>& msg) override {
107 float angle;
108 switch (msg.content) {
109 case MessageContent::Throttle:
110 if (msg.unit != Unit::Percent) return false;
111 setThrottle(static_cast<int>(msg.value));
112 return true;
113 case MessageContent::Pitch:
114 angle = msg.value;
115 if (!toAngleDegree(angle, msg.unit, angle))
116 return false; // Invalid unit
117 setPitch(angle);
118 return true;
119 case MessageContent::Roll:
120 angle = msg.value;
121 if (!toAngleDegree(angle, msg.unit, angle))
122 return false; // Invalid unit
123 setRoll(angle);
124 return true;
125 case MessageContent::Yaw:
126 angle = msg.value;
127 if (!toAngleDegree(angle, msg.unit, angle))
128 return false; // Invalid unit
129 setYaw(angle);
130 return true;
131 default:
132 return false; // Unhandled message content
133 }
134 }
135
136 std::vector<MessageContent> getControls() const override {
137 return {MessageContent::Throttle, MessageContent::Pitch,
138 MessageContent::Roll, MessageContent::Yaw};
139 }
140
141 DriverT& getMotor(QuadrotorMotorNo motor) { return motors_[motor]; }
142
143 std::vector<IMotor<T>*> getMotors() override {
144 std::vector<IMotor<T>*> motors;
145 for (int i = 0; i < 4; ++i) {
146 motors.push_back(&motors_[i]);
147 }
148 return motors;
149 }
150
151 protected:
152 DriverT motors_[4];
153 float motorGain_[4] = {1.0f, 1.0f, 1.0f, 1.0f};
154 float throttle_ = 0;
155 float roll_ = 0;
156 float pitch_ = 0;
157 float yaw_ = 0;
158
159 /**
160 * @brief Update all motors based on throttle, roll, pitch, and yaw.
161 *
162 * This is a simple mixer for an X-configuration quadrotor:
163 * - m1: front left
164 * - m2: front right
165 * - m3: rear left
166 * - m4: rear right
167 *
168 * Each control input is in percent (-100 to 100).
169 */
170 void updateMotors() {
171 // Basic mixing: throttle + pitch/roll/yaw
172 int m[4];
173 m[0] = throttle_ + pitch_ + roll_ - yaw_;
174 m[1] = throttle_ + pitch_ - roll_ + yaw_;
175 m[2] = throttle_ - pitch_ + roll_ + yaw_;
176 m[3] = throttle_ - pitch_ - roll_ - yaw_;
177 for (int i = 0; i < 4; ++i) {
178 int calibrated = static_cast<int>(m[i] * motorGain_[i]);
179 motors_[i].setSpeed(constrain(calibrated, 0, 100));
180 }
181 // publish motor speeds as messages for telemetry
182 for (int i = 0; i < 4; ++i) {
183 Message<float> msg(MessageContent::MotorSpeed, m[i], Unit::Percent);
184 msg.origin = MessageOrigin::Motor;
185 msg.origin_id = i; // Motor index
186 Vehicle<T>::sendMessage(msg);
187 }
188 }
189};
190
191} // namespace tinyrobotics
High-level H-Bridge motor driver class for bidirectional DC motor control.
Definition: BrushedMotor.h:36
Simple quadrotor (quadcopter) model with 4-motor control.
Definition: Quadrotor.h:41
void setPitch(float percent)
Definition: Quadrotor.h:67
void setMotorGain(QuadrotorMotorNo motor, float gain)
Set a calibration gain for a specific motor (default 1.0).
Definition: Quadrotor.h:95
void setRoll(float percent)
Definition: Quadrotor.h:61
void setThrottle(float percent)
Definition: Quadrotor.h:55
void end() override
Definition: Quadrotor.h:79
void updateMotors()
Update all motors based on throttle, roll, pitch, and yaw.
Definition: Quadrotor.h:170
void setYaw(float percent)
Definition: Quadrotor.h:73
bool isPinsSet() const
Check if the necessary pins for the vehicle's actuators have been set (pure virtual).
Definition: Quadrotor.h:99
bool onMessage(const Message< float > &msg) override
Handle an incoming message (pure virtual).
Definition: Quadrotor.h:106
void setPins(QuadrotorMotorNo motor, int in1, int in2)
Set the pins for a specific motor (0=front left, 1=front right, 2=rear left, 3=rear right)
Definition: Quadrotor.h:49
Abstract base class for all vehicle types.
Definition: Vehicle.h:26
Generic message structure for communication, parameterized by value type.
Definition: Message.h:72