cmvr-es/cmvr-es/devices/dexhand/rh56dftp_dexhand/include/rh56dftp_tactile_buffer.h

140 lines
7.0 KiB
C++

#ifndef RH56DFTP_TACTILE_BUFFER_H
#define RH56DFTP_TACTILE_BUFFER_H
#pragma once
#include <array>
#include <cstddef>
#include <stdexcept>
#include "../../abstract_dexhand.h"
namespace cmvr::device {
enum class RH56TactileFillOrder {
ROW_MAJOR,
COLUMN_MAJOR_TOP_TO_BOTTOM,
COLUMN_MAJOR_BOTTOM_TO_TOP
};
struct RH56TactileRegionLayout {
AbstractDexHand::FingerType finger{AbstractDexHand::FingerType::PINKY};
AbstractDexHand::TactileRegion region{AbstractDexHand::TactileRegion::TIP};
const char* name{nullptr};
int rows{0};
int cols{0};
size_t offset{0};
size_t point_count{0};
RH56TactileFillOrder fill_order{RH56TactileFillOrder::ROW_MAJOR};
AbstractDexHand::TactileMatrixView view(const AbstractDexHand::TactilePoint* buffer) const {
return AbstractDexHand::TactileMatrixView{buffer + offset, rows, cols};
}
};
class RH56TactileBuffer {
public:
static constexpr size_t REGION_COUNT = 17;
static constexpr size_t POINT_COUNT = 1062;
void clear() {
values_.fill(0);
}
void assignRegionData(AbstractDexHand::FingerType finger,
AbstractDexHand::TactileRegion region,
const AbstractDexHand::TactilePoint* input,
int valueCount) {
const auto& layout = regionLayout(finger, region);
auto* destination = values_.data() + layout.offset;
const auto sanitize_point = [](const AbstractDexHand::TactilePoint value) {
return value > static_cast<AbstractDexHand::TactilePoint>(4096) ? 0 : value;
};
int input_index = 0;
if (layout.fill_order == RH56TactileFillOrder::ROW_MAJOR) {
for (size_t point = 0; point < layout.point_count && input_index < valueCount; ++point, ++input_index) {
destination[point] = sanitize_point(input[input_index]);
}
return;
}
const bool reverse_rows = layout.fill_order == RH56TactileFillOrder::COLUMN_MAJOR_BOTTOM_TO_TOP;
for (int col = 0; col < layout.cols; ++col) {
for (int row_index = 0; row_index < layout.rows && input_index < valueCount; ++row_index, ++input_index) {
const int row = reverse_rows ? (layout.rows - 1 - row_index) : row_index;
destination[static_cast<size_t>(row * layout.cols + col)] = sanitize_point(input[input_index]);
}
}
}
const RH56TactileRegionLayout& regionLayout(AbstractDexHand::FingerType finger,
AbstractDexHand::TactileRegion region) const {
return layouts()[findRegionIndex(finger, region)];
}
AbstractDexHand::TactileMatrixView regionView(AbstractDexHand::FingerType finger,
AbstractDexHand::TactileRegion region) const {
const auto& layout = regionLayout(finger, region);
return layout.view(values_.data());
}
const std::array<RH56TactileRegionLayout, REGION_COUNT>& layouts() const {
return staticLayouts();
}
const AbstractDexHand::TactilePoint* data() const {
return values_.data();
}
private:
static const std::array<RH56TactileRegionLayout, REGION_COUNT>& staticLayouts() {
static const std::array<RH56TactileRegionLayout, REGION_COUNT> layouts = {{
{AbstractDexHand::FingerType::PINKY, AbstractDexHand::TactileRegion::TIP, "小拇指指端", 3, 3, 0, 9, RH56TactileFillOrder::ROW_MAJOR},
{AbstractDexHand::FingerType::PINKY, AbstractDexHand::TactileRegion::FINGER, "小拇指指尖", 12, 8, 9, 96, RH56TactileFillOrder::ROW_MAJOR},
{AbstractDexHand::FingerType::PINKY, AbstractDexHand::TactileRegion::PAD, "小拇指指腹", 10, 8, 105, 80, RH56TactileFillOrder::ROW_MAJOR},
{AbstractDexHand::FingerType::RING, AbstractDexHand::TactileRegion::TIP, "无名指指端", 3, 3, 185, 9, RH56TactileFillOrder::ROW_MAJOR},
{AbstractDexHand::FingerType::RING, AbstractDexHand::TactileRegion::FINGER, "无名指指尖", 12, 8, 194, 96, RH56TactileFillOrder::ROW_MAJOR},
{AbstractDexHand::FingerType::RING, AbstractDexHand::TactileRegion::PAD, "无名指指腹", 10, 8, 290, 80, RH56TactileFillOrder::ROW_MAJOR},
{AbstractDexHand::FingerType::MIDDLE, AbstractDexHand::TactileRegion::TIP, "中指指端", 3, 3, 370, 9, RH56TactileFillOrder::ROW_MAJOR},
{AbstractDexHand::FingerType::MIDDLE, AbstractDexHand::TactileRegion::FINGER, "中指指尖", 12, 8, 379, 96, RH56TactileFillOrder::ROW_MAJOR},
{AbstractDexHand::FingerType::MIDDLE, AbstractDexHand::TactileRegion::PAD, "中指指腹", 10, 8, 475, 80, RH56TactileFillOrder::ROW_MAJOR},
{AbstractDexHand::FingerType::INDEX, AbstractDexHand::TactileRegion::TIP, "食指指端", 3, 3, 555, 9, RH56TactileFillOrder::ROW_MAJOR},
{AbstractDexHand::FingerType::INDEX, AbstractDexHand::TactileRegion::FINGER, "食指指尖", 12, 8, 564, 96, RH56TactileFillOrder::ROW_MAJOR},
{AbstractDexHand::FingerType::INDEX, AbstractDexHand::TactileRegion::PAD, "食指指腹", 10, 8, 660, 80, RH56TactileFillOrder::ROW_MAJOR},
{AbstractDexHand::FingerType::THUMB, AbstractDexHand::TactileRegion::TIP, "大拇指指端", 3, 3, 740, 9, RH56TactileFillOrder::ROW_MAJOR},
{AbstractDexHand::FingerType::THUMB, AbstractDexHand::TactileRegion::FINGER, "大拇指尖", 12, 8, 749, 96, RH56TactileFillOrder::ROW_MAJOR},
{AbstractDexHand::FingerType::THUMB, AbstractDexHand::TactileRegion::THUMB_MIDDLE, "大拇指指中", 3, 3, 845, 9, RH56TactileFillOrder::ROW_MAJOR},
{AbstractDexHand::FingerType::THUMB, AbstractDexHand::TactileRegion::PAD, "大拇指指腹", 12, 8, 854, 96, RH56TactileFillOrder::ROW_MAJOR},
{AbstractDexHand::FingerType::PALM,
AbstractDexHand::TactileRegion::PALM_PAD,
"掌心",
8,
14,
950,
112,
RH56TactileFillOrder::COLUMN_MAJOR_TOP_TO_BOTTOM}
}};
return layouts;
}
static size_t findRegionIndex(AbstractDexHand::FingerType finger, AbstractDexHand::TactileRegion region) {
const auto& region_layouts = staticLayouts();
for (size_t index = 0; index < region_layouts.size(); ++index) {
if (region_layouts[index].finger == finger && region_layouts[index].region == region) {
return index;
}
}
throw std::invalid_argument("Invalid tactile region for selected finger.");
}
std::array<AbstractDexHand::TactilePoint, POINT_COUNT> values_{};
};
}
#endif //RH56DFTP_TACTILE_BUFFER_H