File drc.hpp
File List > include > libhal-rmd > drc.hpp
Go to the documentation of this file
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
#include <cstdint>
#include <libhal-canrouter/can_router.hpp>
#include <libhal/angular_velocity_sensor.hpp>
#include <libhal/can.hpp>
#include <libhal/motor.hpp>
#include <libhal/rotation_sensor.hpp>
#include <libhal/servo.hpp>
#include <libhal/steady_clock.hpp>
#include <libhal/temperature_sensor.hpp>
#include <libhal/units.hpp>
namespace hal::rmd {
class drc
{
public:
enum class read : hal::byte
{
multi_turns_angle = 0x92,
status_1_and_error_flags = 0x9A,
status_2 = 0x9C,
};
enum class actuate : hal::byte
{
speed = 0xA2,
position_2 = 0xA4,
};
enum class write : hal::byte
{
pid_to_ram = 0x31,
pid_to_rom = 0x32,
acceleration_data_to_ram = 0x34,
encoder_offset = 0x91,
current_position_to_rom_as_motor_zero = 0x19,
};
enum class system : hal::byte
{
clear_error_flag = 0x9B,
off = 0x80,
stop = 0x81,
running = 0x88,
};
struct feedback_t
{
std::uint32_t message_number = 0;
std::int64_t raw_multi_turn_angle{ 0 };
std::int16_t raw_current{ 0 };
std::int16_t raw_speed{ 0 };
std::int16_t raw_volts{ 0 };
std::int16_t encoder{ 0 };
std::int8_t raw_motor_temperature{ 0 };
std::uint8_t raw_error_state{ 0 };
hal::ampere current() const noexcept;
hal::rpm speed() const noexcept;
hal::volts volts() const noexcept;
hal::celsius temperature() const noexcept;
hal::degrees angle() const noexcept;
bool over_voltage_protection_tripped() const noexcept;
bool over_temperature_protection_tripped() const noexcept;
};
[[nodiscard]] static result<drc> create(
hal::can_router& p_router,
hal::steady_clock& p_clock,
float p_gear_ratio,
can::id_t device_id,
hal::time_duration p_max_response_time = std::chrono::milliseconds(10));
drc(drc& p_other) = delete;
drc& operator=(drc& p_other) = delete;
drc(drc&& p_other) noexcept;
drc& operator=(drc&& p_other) noexcept;
[[nodiscard]] status feedback_request(read p_command);
[[nodiscard]] status velocity_control(rpm p_speed);
[[nodiscard]] status position_control(degrees p_angle, rpm speed);
[[nodiscard]] status system_control(system p_system_command);
const feedback_t& feedback() const;
void operator()(const can::message_t& p_message);
private:
drc(hal::can_router& p_router,
hal::steady_clock& p_clock,
float p_gear_ratio,
can::id_t p_device_id,
hal::time_duration p_max_response_time);
friend struct response_waiter;
feedback_t m_feedback{};
hal::steady_clock* m_clock;
hal::can_router* m_router;
hal::can_router::route_item m_route_item;
float m_gear_ratio;
can::id_t m_device_id;
hal::time_duration m_max_response_time;
};
class drc_rotation_sensor : public hal::rotation_sensor
{
private:
drc_rotation_sensor(drc& p_drc);
result<hal::rotation_sensor::read_t> driver_read() override;
friend result<drc_rotation_sensor> make_rotation_sensor(drc& p_drc);
drc* m_drc = nullptr;
};
result<drc_rotation_sensor> make_rotation_sensor(drc& p_drc);
class drc_temperature_sensor : public hal::temperature_sensor
{
private:
drc_temperature_sensor(drc& p_drc);
result<read_t> driver_read() override;
friend result<drc_temperature_sensor> make_temperature_sensor(drc& p_drc);
drc* m_drc = nullptr;
};
result<drc_temperature_sensor> make_temperature_sensor(drc& p_drc);
class drc_motor : public hal::motor
{
public:
friend result<drc_motor> make_motor(drc& p_drc, hal::rpm p_max_speed);
private:
drc_motor(drc& p_drc, hal::rpm p_max_speed);
result<power_t> driver_power(float p_power) override;
drc* m_drc = nullptr;
hal::rpm m_max_speed;
};
result<drc_motor> make_motor(drc& p_drc, hal::rpm p_max_speed);
class drc_servo : public hal::servo
{
private:
drc_servo(drc& p_drc, hal::rpm p_max_speed);
result<position_t> driver_position(hal::degrees p_position) override;
friend result<drc_servo> make_servo(drc& p_drc, hal::rpm p_max_speed);
drc* m_drc = nullptr;
hal::rpm m_max_speed;
};
result<drc_servo> make_servo(drc& p_drc, hal::rpm p_max_speed);
class drc_angular_velocity_sensor : public hal::angular_velocity_sensor
{
private:
drc_angular_velocity_sensor(drc& p_drc);
result<angular_velocity_sensor::read_t> driver_read() override;
friend result<drc_angular_velocity_sensor> make_angular_velocity_sensor(
drc& p_drc);
drc* m_drc = nullptr;
};
result<drc_angular_velocity_sensor> make_angular_velocity_sensor(drc& p_drc);
} // namespace hal::rmd
namespace hal {
using rmd::make_angular_velocity_sensor;
using rmd::make_motor;
using rmd::make_rotation_sensor;
using rmd::make_servo;
using rmd::make_temperature_sensor;
} // namespace hal