第15回 解答例
マイコン向け設計をまとめる
演習の解答例。まず自分で書いてから読むこと。
ファイル構成
include/ ├── Sensor.hpp 抽象クラス(約束ごと) ├── IMU.hpp Sensorを継承 ├── LED.hpp ├── Motor.hpp └── FlightMode.hpp enum class src/ ├── IMU.cpp ├── LED.cpp ├── Motor.cpp └── main.cpp
Sensor / FlightMode
#pragma once
class Sensor {
public:
virtual ~Sensor() = default;
virtual void update() = 0;
};#pragma once
enum class FlightMode {
MANUAL,
AUTO,
LANDING
};IMU
#pragma once
#include "Sensor.hpp"
class IMU : public Sensor {
public:
IMU();
void update() override;
float getRoll() const;
float getPitch() const;
float getYaw() const;
private:
float roll;
float pitch;
float yaw;
};#include "IMU.hpp"
IMU::IMU()
: roll(0.0f), pitch(0.0f), yaw(0.0f) {
}
void IMU::update() {
// 実機では姿勢センサから読み取る
}
float IMU::getRoll() const {
return roll;
}
float IMU::getPitch() const {
return pitch;
}
float IMU::getYaw() const {
return yaw;
}main.cpp
#include <Arduino.h>
#include "FlightMode.hpp"
#include "IMU.hpp"
#include "LED.hpp"
#include "Motor.hpp"
#include "Sensor.hpp"
LED led(LED_BUILTIN);
Motor motor(24);
IMU imu;
Sensor* sensors[] = {&imu};
const int SENSOR_COUNT = sizeof(sensors) / sizeof(sensors[0]);
FlightMode mode = FlightMode::MANUAL;
void setup() {
Serial.begin(115200);
led.begin();
motor.begin();
}
void loop() {
for (int i = 0; i < SENSOR_COUNT; i++) {
sensors[i]->update();
}
switch (mode) {
case FlightMode::MANUAL:
led.off();
break;
case FlightMode::AUTO:
led.on();
motor.setSpeed(50);
break;
case FlightMode::LANDING:
led.toggle();
motor.stop();
break;
}
delay(50);
}main.cppが長くなってきたら
上のmain.cppには、まだ「モードごとの制御判断」が残っている。これをControllerクラスに移し、さらに全体をRobotがまとめると、main.cppは次の形まで短くなる。
#include "Robot.hpp"
Robot robot;
void setup() {
robot.initialize();
}
void loop() {
robot.update();
}これが最終課題で目指す形である。
使った機能の確認
| 要素 | 使っている機能 | 学んだ回 |
|---|---|---|
LED / Motor | クラス・カプセル化・.hpp / .cpp分割 | 第6〜8回 |
Sensor | 抽象クラス・純粋仮想関数 | 第12回 |
IMU | 継承・override | 第10〜11回 |
sensors[] | ポリモーフィズム | 第13回 |
FlightMode | enum classによる状態管理 | 第9回 |
| 全体の構成 | 1クラス1責務 | 第14回 |
ここまで書けていれば、到達度チェックの「設計」の項目はほぼ埋まるはずである。