File mc_x.hpp
File List > include > libhal-rmd > mc_x.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/can.hpp>
#include <libhal/current_sensor.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 mc_x
{
public:
enum class read : hal::byte
{
multi_turns_angle = 0x92,
status_1_and_error_flags = 0x9A,
status_2 = 0x9C,
};
enum class actuate : hal::byte
{
torque = 0xA1,
speed = 0xA2,
position = 0xA5,
};
enum class write : hal::byte
{
// None supported currently
};
enum class system : hal::byte
{
off = 0x80,
stop = 0x81,
};
struct feedback_t
{
std::uint32_t message_number = 0;
std::int64_t raw_multi_turn_angle{ 0 };
std::uint16_t raw_error_state{ 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 };
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 motor_stall() const noexcept;
bool low_pressure() const noexcept;
bool over_voltage() const noexcept;
bool over_current() const noexcept;
bool power_overrun() const noexcept;
bool speeding() const noexcept;
bool over_temperature() const noexcept;
bool encoder_calibration_error() const noexcept;
};
[[nodiscard]] static result<mc_x> 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));
mc_x(mc_x& p_other) = delete;
mc_x& operator=(mc_x& p_other) = delete;
mc_x(mc_x&& p_other) noexcept;
mc_x& operator=(mc_x&& p_other) noexcept;
const feedback_t& feedback() const;
[[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);
void operator()(const can::message_t& p_message);
private:
mc_x(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 mc_x_motor : public hal::motor
{
private:
mc_x_motor(mc_x& p_mc_x, hal::rpm p_max_speed);
result<hal::motor::power_t> driver_power(float p_power) override;
friend result<mc_x_motor> make_motor(mc_x& p_mc_x, hal::rpm p_max_speed);
mc_x* m_mc_x = nullptr;
hal::rpm m_max_speed;
};
result<mc_x_motor> make_motor(mc_x& p_mc_x, hal::rpm p_max_speed);
class mc_x_rotation : public hal::rotation_sensor
{
private:
mc_x_rotation(mc_x& p_mc_x);
result<hal::rotation_sensor::read_t> driver_read() override;
friend result<mc_x_rotation> make_rotation_sensor(mc_x& p_mc_x);
mc_x* m_mc_x = nullptr;
};
result<mc_x_rotation> make_rotation_sensor(mc_x& p_mc_x);
class mc_x_servo : public hal::servo
{
private:
mc_x_servo(mc_x& p_mc_x, hal::rpm p_max_speed);
result<hal::servo::position_t> driver_position(
hal::degrees p_position) override;
friend result<mc_x_servo> make_servo(mc_x& p_mc_x, hal::rpm p_max_speed);
mc_x* m_mc_x = nullptr;
hal::rpm m_max_speed;
};
result<mc_x_servo> make_servo(mc_x& p_mc_x, hal::rpm p_max_speed);
class mc_x_temperature : public hal::temperature_sensor
{
private:
mc_x_temperature(mc_x& p_mc_x);
result<hal::temperature_sensor::read_t> driver_read() override;
friend result<mc_x_temperature> make_temperature_sensor(mc_x& p_mc_x);
mc_x* m_mc_x = nullptr;
};
result<mc_x_temperature> make_temperature_sensor(mc_x& p_mc_x);
class mc_x_current_sensor : public hal::current_sensor
{
private:
mc_x_current_sensor(mc_x& p_mc_x);
result<mc_x_current_sensor::read_t> driver_read() override;
friend result<mc_x_current_sensor> make_current_sensor(mc_x& p_mc_x);
mc_x* m_mc_x = nullptr;
};
result<mc_x_current_sensor> make_current_sensor(mc_x& p_mc_x);
} // namespace hal::rmd
namespace hal {
using rmd::make_current_sensor;
using rmd::make_motor;
using rmd::make_rotation_sensor;
using rmd::make_servo;
using rmd::make_temperature_sensor;
} // namespace hal