From fbd67dab6acb9bd02776c05b42c182c7b654490f Mon Sep 17 00:00:00 2001 From: xtkuang <87661715@qq.com> Date: Mon, 28 Sep 2026 15:24:39 +0800 Subject: [PATCH] add oymotion_dexhand --- cmvr-es/config/devices/dexhand/dexhand.pb.txt | 10 + cmvr-es/config/manager/device_manager.pb.txt | 7 + cmvr-es/config/manager/task_manager.pb.txt | 2 +- cmvr-es/devices/dexhand/CMakeLists.txt | 2 + cmvr-es/devices/dexhand/dexhand_factory.h | 5 + .../dexhand/oymotion_ap001/CMakeLists.txt | 12 + .../oymotion_ap001/include/oymotion_ap001.h | 64 ++ .../oymotion_ap001/src/oymotion_ap001.cpp | 166 +++ .../ohand_serial_sdk/include/OHandSerialAPI.h | 1016 +++++++++++++++++ .../lib/libROHSerialAPIStatic.a | Bin 0 -> 41154 bytes .../dexhand_config/dexhand_config.proto | 9 + 11 files changed, 1292 insertions(+), 1 deletion(-) create mode 100644 cmvr-es/devices/dexhand/oymotion_ap001/CMakeLists.txt create mode 100644 cmvr-es/devices/dexhand/oymotion_ap001/include/oymotion_ap001.h create mode 100644 cmvr-es/devices/dexhand/oymotion_ap001/src/oymotion_ap001.cpp create mode 100644 dependency/x86/third_party/ohand_serial_sdk/include/OHandSerialAPI.h create mode 100644 dependency/x86/third_party/ohand_serial_sdk/lib/libROHSerialAPIStatic.a diff --git a/cmvr-es/config/devices/dexhand/dexhand.pb.txt b/cmvr-es/config/devices/dexhand/dexhand.pb.txt index c1730107..8077edd6 100644 --- a/cmvr-es/config/devices/dexhand/dexhand.pb.txt +++ b/cmvr-es/config/devices/dexhand/dexhand.pb.txt @@ -1,4 +1,14 @@ dexhand { + dexhands { + id: "right_hand_ap001" + oymotion_ap001 { + can_interface: "can0" + hand_id: 2 + master_id: 1 + command_timeout_ms: 255 + } + } + dexhands { id: "hand1" rh56dftp { diff --git a/cmvr-es/config/manager/device_manager.pb.txt b/cmvr-es/config/manager/device_manager.pb.txt index 31147f1f..6bbd6cd6 100644 --- a/cmvr-es/config/manager/device_manager.pb.txt +++ b/cmvr-es/config/manager/device_manager.pb.txt @@ -59,6 +59,13 @@ device_manager { } + devices { + id: "right_hand_ap001" + type: DEVICE_TYPE_DEXHAND + config_file: "devices/dexhand/dexhand.pb.txt" + enable: true + } + devices { id: "hand2" type: DEVICE_TYPE_DEXHAND diff --git a/cmvr-es/config/manager/task_manager.pb.txt b/cmvr-es/config/manager/task_manager.pb.txt index 387eebcc..b9261829 100644 --- a/cmvr-es/config/manager/task_manager.pb.txt +++ b/cmvr-es/config/manager/task_manager.pb.txt @@ -27,6 +27,6 @@ task_manager { type: TASK_TYPE_QUIC_EDGE run_mode: TASK_RUN_MODE_BLOCKING_SERVICE config_file: "tasks/quic_edge_task/quic_edge_task.pb.txt" - enable: true + enable: false } } diff --git a/cmvr-es/devices/dexhand/CMakeLists.txt b/cmvr-es/devices/dexhand/CMakeLists.txt index f162ecd8..76393abd 100644 --- a/cmvr-es/devices/dexhand/CMakeLists.txt +++ b/cmvr-es/devices/dexhand/CMakeLists.txt @@ -1,6 +1,7 @@ add_subdirectory(rh56dftp_dexhand) add_subdirectory(px_6ax_gen3) add_subdirectory(zero_sim_touch_dexhand) +add_subdirectory(oymotion_ap001) add_library(dexhand INTERFACE) @@ -11,6 +12,7 @@ target_link_libraries(dexhand cmvr_es::device::rh56dftp_dexhand cmvr_es::device::px_6ax_gen3 cmvr_es::device::zero_sim_touch_dexhand + cmvr_es::device::oymotion_ap001 cmvr_es::proto ) diff --git a/cmvr-es/devices/dexhand/dexhand_factory.h b/cmvr-es/devices/dexhand/dexhand_factory.h index de7ea7d9..b9fb8c60 100644 --- a/cmvr-es/devices/dexhand/dexhand_factory.h +++ b/cmvr-es/devices/dexhand/dexhand_factory.h @@ -11,6 +11,7 @@ #include "devices/dexhand/px_6ax_gen3/include/px_6ax_gen3.h" #include "devices/dexhand/rh56dftp_dexhand/include/rh56dftp_dexhand.h" #include "devices/dexhand/zero_sim_touch_dexhand/include/zero_sim_touch_dexhand.h" +#include "devices/dexhand/oymotion_ap001/include/oymotion_ap001.h" namespace cmvr::device { @@ -37,6 +38,10 @@ public: return std::make_shared( backendWithId_(cfg.id(), cfg.zero_sim_touch())); + case config::DexHandDeviceConfig::kOymotionAp001: + return std::make_shared( + backendWithId_(cfg.id(), cfg.oymotion_ap001())); + case config::DexHandDeviceConfig::BACKEND_NOT_SET: default: { diff --git a/cmvr-es/devices/dexhand/oymotion_ap001/CMakeLists.txt b/cmvr-es/devices/dexhand/oymotion_ap001/CMakeLists.txt new file mode 100644 index 00000000..5559d4c8 --- /dev/null +++ b/cmvr-es/devices/dexhand/oymotion_ap001/CMakeLists.txt @@ -0,0 +1,12 @@ +add_library(oymotion_ap001 STATIC src/oymotion_ap001.cpp) + +set(OHAND_SDK_ROOT "${PROJECT_SOURCE_DIR}/dependency/x86/third_party/ohand_serial_sdk") +add_library(ohand_serial_sdk STATIC IMPORTED) +set_target_properties(ohand_serial_sdk PROPERTIES + IMPORTED_LOCATION "${OHAND_SDK_ROOT}/lib/libROHSerialAPIStatic.a" + INTERFACE_INCLUDE_DIRECTORIES "${OHAND_SDK_ROOT}/include") + +target_include_directories(oymotion_ap001 PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) +target_link_libraries(oymotion_ap001 PRIVATE cmvr_es::hardware cmvr_es::proto ohand_serial_sdk pthread) + +add_library(cmvr_es::device::oymotion_ap001 ALIAS oymotion_ap001) diff --git a/cmvr-es/devices/dexhand/oymotion_ap001/include/oymotion_ap001.h b/cmvr-es/devices/dexhand/oymotion_ap001/include/oymotion_ap001.h new file mode 100644 index 00000000..2597949c --- /dev/null +++ b/cmvr-es/devices/dexhand/oymotion_ap001/include/oymotion_ap001.h @@ -0,0 +1,64 @@ +#ifndef CMVR_ES_OYMOTION_AP001_H +#define CMVR_ES_OYMOTION_AP001_H + +#include +#include +#include +#include + +#include "cmvr/config/dexhand_config/dexhand_config.pb.h" +#include "devices/dexhand/abstract_dexhand.h" + +namespace cmvr::device { + +class OYMotionAP001 final : public AbstractDexHand { +public: + static constexpr size_t MOTOR_COUNT = 6; + explicit OYMotionAP001(const config::OYMotionAP001Config& config); + ~OYMotionAP001() override; + std::string typeName() const override { return "OYMotionAP001"; } + bool init() override; + bool start() override; + bool stop() override; + Status state() const override; + std::string lastError() const override; + void getState(DexHandState& state) override; + void setAngles(const std::vector& values) override; + void setPositions(const std::vector& values) override; + void setVelocities(const std::vector& values) override; + void setForce(const std::vector& values) override; + void setTactilePollingRegions(const std::vector& regions) override; + std::vector getSensorData() override; + TactileRegionData getSensorData(FingerType finger, TactileRegion region) override; + ResultantForce getResultantForce(FingerType finger, TactileRegion region) override; + ForceNewtons getResultantForceNewtons(FingerType finger, TactileRegion region) override; + +private: + static uint32_t sdkMillis(); + static void sdkDelay(uint32_t milliseconds); + static void sdkSend(uint8_t address, uint8_t* data, uint8_t size, void* context); + static void sdkReceive(void* context); + static OYMotionAP001* fromSdkContext(void* context); + bool openSocket(); + bool checkSdkResult(uint8_t result, uint8_t remote_error, const char* operation); + void setFault(const std::string& message); + void setState(Status state); + std::array normalizedPositions(const std::vector& values, int maximum) const; + + config::OYMotionAP001Config config_; + std::string can_interface_; + uint8_t hand_id_{2}; + uint8_t master_id_{1}; + int socket_fd_{-1}; + void* sdk_context_{nullptr}; + mutable std::mutex state_mutex_; + mutable std::mutex io_mutex_; + Status lifecycle_state_{Status::CREATED}; + std::string last_error_; + std::array speeds_{{255, 255, 255, 255, 255, 255}}; + std::array current_positions_{}; + std::vector tactile_regions_; +}; + +} // namespace cmvr::device +#endif diff --git a/cmvr-es/devices/dexhand/oymotion_ap001/src/oymotion_ap001.cpp b/cmvr-es/devices/dexhand/oymotion_ap001/src/oymotion_ap001.cpp new file mode 100644 index 00000000..8496bf98 --- /dev/null +++ b/cmvr-es/devices/dexhand/oymotion_ap001/src/oymotion_ap001.cpp @@ -0,0 +1,166 @@ +#include "devices/dexhand/oymotion_ap001/include/oymotion_ap001.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "OHandSerialAPI.h" +#include "common/base/logging/logger.h" + +namespace cmvr::device { +namespace { +constexpr int kPositionInputMaximum = 2000; +constexpr int kAngleInputMaximum = 1000; +constexpr int kVelocityInputMaximum = 1000; +constexpr int kForceInputMaximum = 3000; +} + +OYMotionAP001::OYMotionAP001(const config::OYMotionAP001Config& config) : config_(config) { + id_ = config.id(); + can_interface_ = config.can_interface().empty() ? "can0" : config.can_interface(); + if (config.hand_id() > 0 && config.hand_id() <= 0xff) hand_id_ = static_cast(config.hand_id()); + if (config.master_id() > 0 && config.master_id() <= 0xff) master_id_ = static_cast(config.master_id()); +} + +OYMotionAP001::~OYMotionAP001() { stop(); } +uint32_t OYMotionAP001::sdkMillis() { + static const auto start = std::chrono::steady_clock::now(); + return static_cast(std::chrono::duration_cast(std::chrono::steady_clock::now() - start).count()); +} +void OYMotionAP001::sdkDelay(uint32_t milliseconds) { std::this_thread::sleep_for(std::chrono::milliseconds(milliseconds)); } +OYMotionAP001* OYMotionAP001::fromSdkContext(void* context) { return context ? *static_cast(context) : nullptr; } + +void OYMotionAP001::sdkSend(uint8_t address, uint8_t* data, uint8_t size, void* context) { + auto* self = fromSdkContext(context); + if (!self || self->socket_fd_ < 0) return; + for (uint8_t offset = 0; offset < size; offset += CAN_MAX_DLEN) { + can_frame frame{}; + frame.can_id = address; + frame.can_dlc = static_cast<__u8>(std::min(CAN_MAX_DLEN, size - offset)); + std::memcpy(frame.data, data + offset, frame.can_dlc); + if (write(self->socket_fd_, &frame, sizeof(frame)) != sizeof(frame)) { + self->setFault("[OYMotionAP001] failed to write CAN frame on " + self->can_interface_); + return; + } + } +} + +void OYMotionAP001::sdkReceive(void* context) { + auto* self = fromSdkContext(context); + if (!self || self->socket_fd_ < 0) return; + can_frame frame{}; + while (read(self->socket_fd_, &frame, sizeof(frame)) == sizeof(frame)) { + if ((frame.can_id & CAN_EFF_FLAG) || (frame.can_id & CAN_RTR_FLAG)) continue; + for (uint8_t i = 0; i < frame.can_dlc; ++i) HAND_OnData(context, frame.data[i]); + } +} + +bool OYMotionAP001::openSocket() { + socket_fd_ = socket(PF_CAN, SOCK_RAW, CAN_RAW); + if (socket_fd_ < 0) return false; + ifreq request{}; + std::strncpy(request.ifr_name, can_interface_.c_str(), IFNAMSIZ - 1); + if (ioctl(socket_fd_, SIOCGIFINDEX, &request) < 0) return false; + sockaddr_can address{}; + address.can_family = AF_CAN; + address.can_ifindex = request.ifr_ifindex; + if (bind(socket_fd_, reinterpret_cast(&address), sizeof(address)) < 0) return false; + const int flags = fcntl(socket_fd_, F_GETFL, 0); + return flags >= 0 && fcntl(socket_fd_, F_SETFL, flags | O_NONBLOCK) == 0; +} + +bool OYMotionAP001::init() { + std::lock_guard io_lock(io_mutex_); + if (sdk_context_) return true; + if (!openSocket()) { setFault("[OYMotionAP001] cannot open " + can_interface_ + "; ensure it is UP at 1 Mbps"); return false; } + HAND_SetTimerFunction(sdkMillis, sdkDelay); + sdk_context_ = HAND_CreateContext(this, HAND_PROTOCOL_UART, master_id_, sdkSend, sdkReceive); + if (!sdk_context_) { setFault("[OYMotionAP001] HAND_CreateContext failed"); return false; } + HAND_SetCommandTimeOut(sdk_context_, static_cast(config_.command_timeout_ms() > 0 ? std::min(config_.command_timeout_ms(), 65535) : 255)); + uint8_t major = 0, minor = 0, remote_error = 0; + if (!checkSdkResult(HAND_GetProtocolVersion(sdk_context_, hand_id_, &major, &minor, &remote_error), remote_error, "HAND_GetProtocolVersion")) return false; + CMVR_LOG(INFO) << "[OYMotionAP001] connected: id=" << id_ << ", interface=" << can_interface_ << ", hand_id=" << static_cast(hand_id_) << ", protocol=" << static_cast(major) << "." << static_cast(minor); + setState(Status::INITIALIZED); + return true; +} + +bool OYMotionAP001::start() { if (!init()) return false; setState(Status::STREAMING); return true; } +bool OYMotionAP001::stop() { + std::lock_guard io_lock(io_mutex_); + if (sdk_context_) { HAND_FreeContext(sdk_context_); sdk_context_ = nullptr; } + if (socket_fd_ >= 0) { close(socket_fd_); socket_fd_ = -1; } + if (state() != Status::FAULT) setState(Status::STOPPED); + return true; +} +AbstractDexHand::Status OYMotionAP001::state() const { std::lock_guard lock(state_mutex_); return lifecycle_state_; } +std::string OYMotionAP001::lastError() const { std::lock_guard lock(state_mutex_); return last_error_; } + +void OYMotionAP001::getState(DexHandState& output) { + DexHandState next{}; + next.is_initialized = state() == Status::INITIALIZED || state() == Status::STREAMING; + std::lock_guard io_lock(io_mutex_); + if (sdk_context_) { + std::array targets{}, positions{}; + uint8_t count = 0, remote_error = 0; + if (HAND_GetFingerPosAll(sdk_context_, hand_id_, targets.data(), positions.data(), &count, &remote_error) == HAND_RESP_SUCCESS) current_positions_ = positions; + } + for (size_t i = 0; i < MOTOR_COUNT; ++i) { + next.hands[i].position = static_cast(current_positions_[i]) * kPositionInputMaximum / 65535; + next.hands[i].angle = static_cast(current_positions_[i]) * kAngleInputMaximum / 65535; + next.hands[i].speed = static_cast(speeds_[i]) * kVelocityInputMaximum / 255; + } + const auto error = lastError(); + if (!error.empty()) next.hands[0].error_message.push_back(error); + output = std::move(next); +} + +std::array OYMotionAP001::normalizedPositions(const std::vector& values, int maximum) const { + if (values.size() != MOTOR_COUNT) throw std::invalid_argument("OYMotionAP001 expects exactly 6 values"); + std::array output{}; + for (size_t i = 0; i < MOTOR_COUNT; ++i) output[i] = static_cast(static_cast(std::clamp(values[i], 0, maximum)) * 65535U / maximum); + return output; +} + +void OYMotionAP001::setPositions(const std::vector& values) { + auto positions = normalizedPositions(values, kPositionInputMaximum); + std::lock_guard lock(io_mutex_); uint8_t remote_error = 0; + checkSdkResult(HAND_SetFingerPosAll(sdk_context_, hand_id_, positions.data(), speeds_.data(), MOTOR_COUNT, &remote_error), remote_error, "HAND_SetFingerPosAll"); +} +void OYMotionAP001::setAngles(const std::vector& values) { + auto positions = normalizedPositions(values, kAngleInputMaximum); + std::lock_guard lock(io_mutex_); uint8_t remote_error = 0; + checkSdkResult(HAND_SetFingerPosAll(sdk_context_, hand_id_, positions.data(), speeds_.data(), MOTOR_COUNT, &remote_error), remote_error, "HAND_SetFingerPosAll(angle normalization)"); +} +void OYMotionAP001::setVelocities(const std::vector& values) { + if (values.size() != MOTOR_COUNT) throw std::invalid_argument("OYMotionAP001 expects exactly 6 velocities"); + std::lock_guard lock(io_mutex_); + for (size_t i = 0; i < MOTOR_COUNT; ++i) speeds_[i] = static_cast(std::clamp(values[i], 0, kVelocityInputMaximum) * 255 / kVelocityInputMaximum); +} +void OYMotionAP001::setForce(const std::vector& values) { + if (values.size() != MOTOR_COUNT) throw std::invalid_argument("OYMotionAP001 expects exactly 6 force values"); + std::lock_guard lock(io_mutex_); + for (size_t i = 0; i < MOTOR_COUNT; ++i) { uint8_t remote_error = 0; if (!checkSdkResult(HAND_SetFingerForceTarget(sdk_context_, hand_id_, static_cast(i), static_cast(std::clamp(values[i], 0, kForceInputMaximum)), &remote_error), remote_error, "HAND_SetFingerForceTarget")) return; } +} + +void OYMotionAP001::setTactilePollingRegions(const std::vector& regions) { tactile_regions_ = regions; } +std::vector OYMotionAP001::getSensorData() { return {}; } +AbstractDexHand::TactileRegionData OYMotionAP001::getSensorData(FingerType, TactileRegion) { return {}; } +AbstractDexHand::ResultantForce OYMotionAP001::getResultantForce(FingerType, TactileRegion) { return {}; } +AbstractDexHand::ForceNewtons OYMotionAP001::getResultantForceNewtons(FingerType, TactileRegion) { return {}; } + +bool OYMotionAP001::checkSdkResult(uint8_t result, uint8_t remote_error, const char* operation) { + if (result == HAND_RESP_SUCCESS) return true; + setFault("[OYMotionAP001] " + std::string(operation) + " failed: result=" + std::to_string(result) + ", remote_error=" + std::to_string(remote_error)); + return false; +} +void OYMotionAP001::setFault(const std::string& message) { { std::lock_guard lock(state_mutex_); lifecycle_state_ = Status::FAULT; last_error_ = message; } CMVR_LOG(ERROR) << message; } +void OYMotionAP001::setState(Status next) { std::lock_guard lock(state_mutex_); lifecycle_state_ = next; if (next == Status::INITIALIZED || next == Status::STREAMING) last_error_.clear(); } +} // namespace cmvr::device diff --git a/dependency/x86/third_party/ohand_serial_sdk/include/OHandSerialAPI.h b/dependency/x86/third_party/ohand_serial_sdk/include/OHandSerialAPI.h new file mode 100644 index 00000000..e58c6818 --- /dev/null +++ b/dependency/x86/third_party/ohand_serial_sdk/include/OHandSerialAPI.h @@ -0,0 +1,1016 @@ + +/* Define to prevent recursive inclusion -------------------------------------*/ + +#ifndef __HAND_SERIAL_API_H__ +#define __HAND_SERIAL_API_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ + +#include + + +/* Exported types ------------------------------------------------------------*/ + +#ifndef NULL +#define NULL ((void*)0) +#endif + +#ifndef BOOL +#define BOOL uint8_t +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + + +/* Exported constants --------------------------------------------------------*/ + +#define MAX_THUMB_ROOT_POS 3 +#define MAX_MOTOR_CNT 6 +#define MAX_FORCE_ENTRIES 12 * 5 /* Max force entries for one finger */ + + +typedef enum +{ + HAND_PROTOCOL_UART, + HAND_PROTOCOL_I2C +} HAND_PROTOCOL; + + +#define PROTOCOL_VERSION_MAJOR 3 + + +/* + * OHand error codes + */ + +/* + * Error codes for remote peer, protocol part + */ +#define ERR_PROTOCOL_WRONG_LRC 0x01 + + +/* + * Error codes for remote peer, command part + */ +#define ERR_COMMAND_INVALID 0x11 +#define ERR_COMMAND_INVALID_BYTE_COUNT 0x12 +#define ERR_COMMAND_INVALID_DATA 0x13 + + +/* + * Error codes for remote peer, status part + */ +#define ERR_STATUS_INIT 0x21 +#define ERR_STATUS_CALI 0x22 +#define ERR_STATUS_STUCK 0x23 + + +/* + * Error codes for remote peer, operation result part + */ +#define ERR_OP_FAILED 0x31 +#define ERR_SAVE_FAILED 0x32 + + +/* + * API return values + */ +#define HAND_RESP_HAND_ERROR 0xFF /* device error, error call back will be called with OHand error codes listed above */ + +#define HAND_RESP_SUCCESS 0x00 +#define HAND_RESP_TIMER_FUNC_NOT_SET 0x01 /* local error, timer function not set, call HAND_SetTimerFunction(...) first */ +#define HAND_RESP_INVALID_CONTEXT 0x02 /* local error, invalid context, NULL or send data function not set */ +#define HAND_RESP_TIMEOUT 0x03 /* local error, time out when waiting node response */ +#define HAND_RESP_INVALID_OUT_BUFFER_SIZE 0x04 /* local error, out buffer size not matched to returned data */ +#define HAND_RESP_UNMATCHED_ADDR 0x05 /* local error, unmatched node id between returned and waiting */ +#define HAND_RESP_UNMATCHED_CMD 0x06 /* local error, unmatched command between returned and waiting */ +#define HAND_RESP_DATA_SIZE_TOO_BIG 0x07 /* local error, size of data to send exceeds the buffer size */ +#define HAND_RESP_DATA_INVALID 0x08 /* local error, data content invalid */ + + +/* Sub-command for HAND_CMD_SET_CUSTOM */ +#define SUB_CMD_SET_SPEED (1 << 0) +#define SUB_CMD_SET_POS (1 << 1) +#define SUB_CMD_SET_ANGLE (1 << 2) +#define SUB_CMD_GET_POS (1 << 3) +#define SUB_CMD_GET_ANGLE (1 << 4) +#define SUB_CMD_GET_CURRENT (1 << 5) +#define SUB_CMD_GET_FORCE (1 << 6) +#define SUB_CMD_GET_STATUS (1 << 7) + + +/* Exported macro ------------------------------------------------------------*/ + + + +/* Exported functions ------------------------------------------------------- */ + +/* + * OHand Serial API + */ + +/** + * @brief Create context and set master address, send data function and receive data function + * @note For none interrupt receive function, pass receive function pointer as parameter + * RecvDataImpl and call HAND_OnData(...) in receive function. For interrupt receive + * mode, pass NULL as parameter RecvDataImpl and call HAND_OnData(...) in ISR. Call + * this before using other get & set functions + * @param ctx_private_data: Context private data, e.g., address of serial port instance, + * port name string, etc. Resource should be available during runtime. + * @param protocol: HAND_PROTOCOL_UART or HAND_PROTOCOL_I2C + * @param address_master: master node address + * @param SendDataImpl: send data function pointer + * @param RecvDataImpl: receive data function pointer, NULL for interrupt receive mode + * @retval Context + */ +void *HAND_CreateContext( + const void *ctx_private_data, + HAND_PROTOCOL protocol, + uint8_t address_master, + void (*SendDataImpl)(uint8_t addr, uint8_t *data, uint8_t size, void *ctx), + void (*RecvDataImpl)(void *ctx) +); + + +/** + * @brief Free OHand context + * @param ctx: pointer to OHand context + * @retval None + */ +void HAND_FreeContext(void *ctx); + + +/** + * @brief Set timer related function + * @note Call this before using get & set functions + * @param GetMilliSecondsImpl: pointer of function to get miliseconds + * @param DelayMilliSecondsImpl: pointer of function to delay miliseconds + * @retval None + */ +void HAND_SetTimerFunction(uint32_t (*GetMilliSecondsImpl)(void), void (*DelayMilliSecondsImpl)(uint32_t ms)); + + +/** + * @brief Get current tick of system in milliseconds + * @note if HAND_SetTimerFunction(...) is not set, this will always return 0 + * @param None + * @retval None + */ +uint32_t HAND_GetTick(void); + + +/** + * @brief Set command timeout value + * @note Call this before using get & set functions. Default value is 255ms + * @param ctx: pointer to OHand context + * @param timeout: timeout in miliseconds + * @param DelayMilliSecondsImpl: pointer of function to delay miliseconds + * @retval None + */ +void HAND_SetCommandTimeOut(void *ctx, uint16_t timeout); + + +/** + * @brief Feed data to internal parser + * @note Call this in data receive function, either RecvDataImpl or ISR + * @param ctx: pointer to OHand context + * @param data: data byte received + * @retval None + */ +void HAND_OnData(void *ctx, uint8_t data); + + + +/* + * Gets + */ + +/** + * @brief Get protocol version + * @note + * @param ctx: pointer to OHand context + * @param hand_id: id of OHand + * @param major: pointer to uint8_t type var, when success, the major version of firmware will be stored + * @param minor: pointer to uint8_t type var, when success, the minor version of firmware will be stored + * @param remote_err: address to put remote node error in case of HAND_RESP_HAND_ERROR + * @retval -HAND_RESP_SUCCESS: success + * -Others: failed, see definition of API return values + */ +uint8_t HAND_GetProtocolVersion(void *ctx, uint8_t hand_id, uint8_t *major, uint8_t *minor, uint8_t *remote_err); + +/** + * @brief Get firmware version + * @note + * @param ctx: pointer to OHand context + * @param hand_id: id of OHand + * @param major: pointer to uint8_t type var, when success, the major version of firmware will be stored + * @param minor: pointer to uint8_t type var, when success, the minor version of firmware will be stored + * @param revision: pointer to uint16_t type var, when success, the revision of firmware will be stored + * @param remote_err: address to put remote node error in case of HAND_RESP_HAND_ERROR + * @retval -HAND_RESP_SUCCESS: success + * -Others: failed, see definition of API return values + */ +uint8_t HAND_GetFirmwareVersion(void *ctx, uint8_t hand_id, uint8_t *major, uint8_t *minor, uint16_t *revision, uint8_t *remote_err); + + +/** + * @brief Get hardware version + * @note + * @param ctx: pointer to OHand context + * @param hand_id: id of OHand + * @param hw_type: pointer to uint8_t type var, when success, the hardware type will be stored + * @param hw_ver: pointer to uint8_t type var, when success, the hardware version will be stored + * @param boot_version: pointer to uint16_t type var, when success, the major version will be stored in high byte, + * while the minor ver in the low byte + * @param remote_err: address to put remote node error in case of HAND_RESP_HAND_ERROR + * @retval -HAND_RESP_SUCCESS: success + * -Others: failed, see definition of API return values + */ +uint8_t HAND_GetHardwareVersion(void *ctx, uint8_t hand_id, uint8_t *hw_type, uint8_t *hw_ver, uint16_t *boot_version, uint8_t *remote_err); + + +/** + * @brief Get calibration data + * @note + * @param ctx: pointer to OHand context + * @param hand_id: id of OHand + * @param end_pos: address of array to put end_pos + * @param start_pos: address of array to put start_pos + * @param motor_cnt: motor count, i.e., array size of end_pos[] or start_pos[] + * @param thumb_root_pos: address of array to put thumb_root_pos + * @param thumb_root_pos_cnt: count of pre-defined thumb root pos + * @param remote_err: address to put remote node error in case of HAND_RESP_HAND_ERROR + * @retval -HAND_RESP_SUCCESS: success + * -Others: failed, see definition of API return values + */ +uint8_t HAND_GetCaliData(void *ctx, uint8_t hand_id, uint16_t *end_pos, uint16_t *start_pos, uint8_t *motor_cnt, uint16_t *thumb_root_pos, uint8_t *thumb_root_pos_cnt, uint8_t *remote_err); + + +/** + * @brief Get PID gain + * @note + * @param ctx: pointer to OHand context + * @param hand_id: id of OHand + * @param finger_id: index of finger + * @param p: address of var to put PID gain p + * @param i: address of var to put PID gain i + * @param d: address of var to put PID gain d + * @param g: address of var to put PID gain g + * @param remote_err: address to put remote node error in case of HAND_RESP_HAND_ERROR + * @retval -HAND_RESP_SUCCESS: success + * -Others: failed, see definition of API return values + */ +uint8_t HAND_GetFingerPID(void *ctx, uint8_t hand_id, uint8_t finger_id, float *p, float *i, float *d, float *g, uint8_t *remote_err); + +/** + * @brief Get Stop Parameter + * @note + * @param hand_id: id of OHand + * @param finger_id: index of finger + * @param speed: address of var to put Stop Parameter speed + * @param current: address of var to put Stop Parameter current + * @param after_period: address of var to put Stop Parameter after_period + * @param retry_period: address of var to put Stop Parameter retry_period + * @retval -RESP_SUCCESS: success + * -Others: failed, see definition of API return values + */ +uint8_t HAND_GetFingerStopParam(void *ctx, uint8_t hand_id, uint8_t finger_id, uint16_t *speed, uint16_t *current, uint16_t *after_period, uint16_t *retry_period, uint8_t *remote_err); + +/** + * @brief Get current limit of finger + * @note + * @param ctx: pointer to OHand context + * @param hand_id: id of OHand + * @param finger_id: index of finger + * @param current_limit: address of var to put current limit in mA + * @param remote_err: address to put remote node error in case of HAND_RESP_HAND_ERROR + * @retval -HAND_RESP_SUCCESS: success + * -Others: failed, see definition of API return values + */ +uint8_t HAND_GetFingerCurrentLimit(void *ctx, uint8_t hand_id, uint8_t finger_id, uint16_t *current_limit, uint8_t *remote_err); + + +/** + * @brief Get current of finger + * @note + * @param ctx: pointer to OHand context + * @param hand_id: id of OHand + * @param finger_id: index of finger + * @param current: address of var to put current in mA + * @param remote_err: address to put remote node error in case of HAND_RESP_HAND_ERROR + * @retval -HAND_RESP_SUCCESS: success + * -Others: failed, see definition of API return values + */ +uint8_t HAND_GetFingerCurrent(void *ctx, uint8_t hand_id, uint8_t finger_id, uint16_t *current, uint8_t *remote_err); + + +/** + * @brief Get target force of finger + * @note + * @param ctx: pointer to OHand context + * @param hand_id: id of OHand + * @param finger_id: index of finger + * @param force_target: address of var to put force target in mN + * @param remote_err: address to put remote node error in case of HAND_RESP_HAND_ERROR + * @retval -HAND_RESP_SUCCESS: success + * -Others: failed, see definition of API return values + */ +uint8_t HAND_GetFingerForceTarget(void *ctx, uint8_t hand_id, uint8_t finger_id, uint16_t *force_target, uint8_t *remote_err); + + +/** + * @brief Get force of finger + * @note + * @param ctx: pointer to OHand context + * @param hand_id: id of OHand + * @param finger_id: actually sensor id + * @param force_entry_cnt: count of force entries + * @param force: address of var to put force, may be multi-point forces, or normal force, tangential force and dir + * @param remote_err: address to put remote node error in case of HAND_RESP_HAND_ERROR + * @retval -HAND_RESP_SUCCESS: success + * -Others: failed, see definition of API return values + */ +uint8_t HAND_GetFingerForce(void *ctx, uint8_t hand_id, uint8_t finger_id, uint8_t *force_entry_cnt, uint8_t *force, uint8_t *remote_err); + + +/** + * @brief Get absolute position limit of finger + * @note + * @param ctx: pointer to OHand context + * @param hand_id: id of OHand + * @param finger_id: id of finger + * @param low_limit: address of var to put low limit of finger position + * @param high_limit: address of var to put high limit of finger position + * @param remote_err: address to put remote node error in case of HAND_RESP_HAND_ERROR + * @retval -HAND_RESP_SUCCESS: success + * -Others: failed, see definition of API return values + */ +uint8_t HAND_GetFingerPosLimit(void *ctx, uint8_t hand_id, uint8_t finger_id, uint16_t *low_limit, uint16_t *high_limit, uint8_t *remote_err); + + +/** + * @brief Get absolute position of finger + * @note + * @param ctx: pointer to OHand context + * @param hand_id: id of OHand + * @param finger_id: id of finger + * @param target_pos: address of var to put raw target position, i.e., encoder value of finger + * @param current_pos: address of var to put raw current position, i.e., encoder value of finger + * @param remote_err: address to put remote node error in case of HAND_RESP_HAND_ERROR + * @retval -HAND_RESP_SUCCESS: success + * -Others: failed, see definition of API return values + */ +uint8_t HAND_GetFingerPosAbs(void *ctx, uint8_t hand_id, uint8_t finger_id, uint16_t *target_pos, uint16_t *current_pos, uint8_t *remote_err); + + +/** + * @brief Get logical position of finger + * @note + * @param ctx: pointer to OHand context + * @param hand_id: id of OHand + * @param finger_id: id of finger + * @param target_pos: address of var to put logical target position + * @param current_pos: address of var to put logical current position + * @param remote_err: address to put remote node error in case of HAND_RESP_HAND_ERROR + * @retval -HAND_RESP_SUCCESS: success + * -Others: failed, see definition of API return values + */ +uint8_t HAND_GetFingerPos(void *ctx, uint8_t hand_id, uint8_t finger_id, uint16_t *target_pos, uint16_t *current_pos, uint8_t *remote_err); + + +/** + * @brief Get angle of finger + * @note + * @param ctx: pointer to OHand context + * @param hand_id: id of OHand + * @param finger_id: id of finger + * @param target_angle: address of var to put logical target position, value = real angle * 100 + * @param current_angle: address of var to put logical current position, value = real angle * 100 + * @param remote_err: address to put remote node error in case of HAND_RESP_HAND_ERROR + * @retval -HAND_RESP_SUCCESS: success + * -Others: failed, see definition of API return values + */ +uint8_t HAND_GetFingerAngle(void *ctx, uint8_t hand_id, uint8_t finger_id, int16_t *target_angle, int16_t *current_angle, uint8_t *remote_err); + + +/** + * @brief Get position of thumb's root + * @note + * @param ctx: pointer to OHand context + * @param hand_id: id of OHand + * @param raw_encoder: address of var to put raw encoder value of thumb's root, value range [0-65535] + * @param pos: address of var to put mapped position of thumb's root, value range [0-2], or 255 if invalid + * @param remote_err: address to put remote node error in case of HAND_RESP_HAND_ERROR + * @retval -HAND_RESP_SUCCESS: success + * -Others: failed, see definition of API return values + */ +uint8_t HAND_GetThumbRootPos(void *ctx, uint8_t hand_id, uint16_t *raw_encoder, uint8_t *pos, uint8_t *remote_err); + + +/** + * @brief Get absolute position of all fingers + * @note + * @param ctx: pointer to OHand context + * @param hand_id: id of OHand + * @param motor_cnt: number of motors + * @param target_pos: address of var to put raw target position, i.e., encoder value of finger + * @param current_pos: address of var to put raw current position, i.e., encoder value of finger + * @param remote_err: address to put remote node error in case of HAND_RESP_HAND_ERROR + * @retval -HAND_RESP_SUCCESS: success + * -Others: failed, see definition of API return values + */ +uint8_t HAND_GetFingerPosAbsAll(void *ctx, uint8_t hand_id, uint16_t *target_pos, uint16_t *current_pos, uint8_t *motor_cnt, uint8_t *remote_err); + + +/** + * @brief Get logical position of all fingers + * @note + * @param ctx: pointer to OHand context + * @param hand_id: id of OHand + * @param target_pos: address of var to put logical target position + * @param current_pos: address of var to put logical current position + * @param motor_cnt: number of motors + * @param remote_err: address to put remote node error in case of HAND_RESP_HAND_ERROR + * @retval -HAND_RESP_SUCCESS: success + * -Others: failed, see definition of API return values + */ +uint8_t HAND_GetFingerPosAll(void *ctx, uint8_t hand_id, uint16_t *target_pos, uint16_t *current_pos, uint8_t *motor_cnt, uint8_t *remote_err); + + +/** + * @brief Get first joint angle of all fingers + * @note + * @param ctx: pointer to OHand context + * @param hand_id: id of OHand + * @param target_angle: address of var to put target angle + * @param current_pos: address of var to put current angle + * @param motor_cnt: number of motors + * @param remote_err: address to put remote node error in case of HAND_RESP_HAND_ERROR + * @retval -HAND_RESP_SUCCESS: success + * -Others: failed, see definition of API return values + */ +uint8_t HAND_GetFingerAngleAll(void *ctx, uint8_t hand_id, int16_t *target_angle, int16_t *current_angle, uint8_t *motor_cnt, uint8_t *remote_err); + + + +/** + * @brief Get self test level + * @note + * @param ctx: pointer to OHand context + * @param hand_id: id of OHand + * @param self_test_on: address of var to put self-test level + * @param remote_err: address to put remote node error in case of HAND_RESP_HAND_ERROR + * @retval -HAND_RESP_SUCCESS: success + * -Others: failed, see definition of API return values + */ +uint8_t HAND_GetSelfTestLevel(void *ctx, uint8_t hand_id, uint8_t *self_test_level, uint8_t *remote_err); + + +/** + * @brief Get beep switch + * @note + * @param ctx: pointer to OHand context + * @param hand_id: id of OHand + * @param beep_on: address of var to put beep switch status + * @param remote_err: address to put remote node error in case of HAND_RESP_HAND_ERROR + * @retval -HAND_RESP_SUCCESS: success + * -Others: failed, see definition of API return values + */ +uint8_t HAND_GetBeepSwitch(void *ctx, uint8_t hand_id, uint8_t *beep_switch, uint8_t *remote_err); + + +/** + * @brief Get button pressed count of OHand + * @note + * @param ctx: pointer to OHand context + * @param hand_id: id of OHand + * @param pressed_cnt: button pressed count + * @param remote_err: address to put remote node error in case of HAND_RESP_HAND_ERROR + * @retval -HAND_RESP_SUCCESS: success + * -Others: failed, see definition of API return values + */ +uint8_t HAND_GetButtonPressedCnt(void *ctx, uint8_t hand_id, uint8_t *pressed_cnt, uint8_t *remote_err); + + +/** + * @brief Get the 96 bits device UID + * @note + * @param ctx: pointer to OHand context + * @param hand_id: id of OHand + * @param uid_w0: pointer to word 0 of UID + * @param uid_w1: pointer to word 1 of UID + * @param uid_w2: pointer to word 2 of UID + * @param remote_err: address to put remote node error in case of HAND_RESP_HAND_ERROR + * @retval -HAND_RESP_SUCCESS: success + * -Others: failed, see definition of API return values + */ +uint8_t HAND_GetUID(void *ctx, uint8_t hand_id, uint32_t *uid_w0, uint32_t *uid_w1, uint32_t *uid_w2, uint8_t *remote_err); + + +/** + * @brief Get battery voltage + * @note + * @param ctx: pointer to OHand context + * @param hand_id: id of OHand + * @param voltage: pointer to uint16_t type var, when success, the voltage in mv will be stored + * @param remote_err: address to put remote node error in case of HAND_RESP_HAND_ERROR + * @retval -HAND_RESP_SUCCESS: success + * -Others: failed, see definition of API return values + */ +uint8_t HAND_GetBatteryVoltage(void *ctx, uint8_t hand_id, uint16_t *voltage, uint8_t *remote_err); + + +/** + * @brief Get usage stat + * @note + * @param ctx: pointer to OHand context + * @param hand_id: id of OHand + * @param total_use_time: address of var to put total use time in seconds + * @param total_open_times: address of array to put total_open_times[5] + * @param motor_cnt: motor count, i.e., array size of total_use_time[] or total_open_times[] + * @param remote_err: address to put remote node error in case of HAND_RESP_HAND_ERROR + * @retval -HAND_RESP_SUCCESS: success + * -Others: failed, see definition of API return values + */ +uint8_t HAND_GetUsageStat(void *ctx, uint8_t hand_id, uint32_t *total_use_time, uint32_t *total_open_times, uint8_t motor_cnt, uint8_t *remote_err); + + +/** + * @brief Get manufacture data + * @note + * @param ctx: pointer to OHand context + * @param hand_id: id of OHand + * @param data: pointer to array to put manufacture data + * @param data_size: address of var to put manufacture data size + * @param remote_err: address to put remote node error in case of HAND_RESP_HAND_ERROR + * @retval -HAND_RESP_SUCCESS: success + * -Others: failed, see definition of API return values + */ +uint8_t HAND_GetManufactureData(void *ctx, uint8_t hand_id, uint8_t *data, uint8_t *data_size, uint8_t *remote_err); + + +/** + * @brief Get vendor id + * @note + * @param ctx: pointer to OHand context + * @param hand_id: id of OHand + * @param vendor_id: address of var to put vendor id + * @param remote_err: address to put remote node error in case of HAND_RESP_HAND_ERROR + * @retval -HAND_RESP_SUCCESS: success + * -Others: failed, see definition of API return values + */ +uint8_t HAND_GetVendorID(void *ctx, uint8_t hand_id, uint16_t *vendor_id, uint8_t *remote_err); + + +/** + * @brief Get force PID gain + * @note + * @param ctx: pointer to OHand context + * @param hand_id: id of OHand + * @param finger_id: index of finger + * @param p: address of var to put PID gain p + * @param i: address of var to put PID gain i + * @param d: address of var to put PID gain d + * @param g: address of var to put PID gain g + * @param remote_err: address to put remote node error in case of HAND_RESP_HAND_ERROR + * @retval -HAND_RESP_SUCCESS: success + * -Others: failed, see definition of API return values + */ +uint8_t HAND_GetForcePID(void *ctx, uint8_t hand_id, uint8_t finger_id, float *p, float *i, float *d, float *g, uint8_t *remote_err); + +/** + * @brief Get Speed Control Parameters of finger + * @note + * @param hand_id: id of OHand + * @param brake_distance: Speed Brake Distance + * @param accel_distance: Speed Accelerate Distance + * @param speed_ratio: PID Speed Ratio + * @retval -RESP_SUCCESS: success + * -Others: failed, see definition of API return values + */ +uint8_t HAND_GetFingerSpeedCtrlParams(void *ctx, uint8_t hand_id, uint16_t *brake_distance, uint16_t *accel_distance, float *speed_ratio, uint8_t* remote_err); + + +/* + * Sets + */ + + /** + * @brief Reset hand + * @note NO response, so return code must be timeout + * @param ctx: pointer to OHand context + * @param hand_id: id of OHand + * @param mode: 0 boot to user code, 1 boot to DFU mode + * @param remote_err: address to put remote node error in case of HAND_RESP_HAND_ERROR + * @retval -HAND_RESP_SUCCESS: success + * -Others: failed, see definition of API return values + */ +uint8_t HAND_Reset(void *ctx, uint8_t hand_id, uint8_t mode, uint8_t *remote_err); + + + /** + * @brief Turn hand off + * @note NO response, so return code must be timeout + * @param ctx: pointer to OHand context + * @param hand_id: id of OHand + * @param remote_err: address to put remote node error in case of HAND_RESP_HAND_ERROR + * @retval -HAND_RESP_SUCCESS: success + * -Others: failed, see definition of API return values + */ +uint8_t HAND_PowerOff(void *ctx, uint8_t hand_id, uint8_t *remote_err); + + +/** + * @brief Set hand id + * @note Need to reboot device after setting + * @param ctx: pointer to OHand context + * @param hand_id: id of OHand + * @param new_id: new id for hand + * @param remote_err: address to put remote node error in case of HAND_RESP_HAND_ERROR + * @retval -HAND_RESP_SUCCESS: success + * -Others: failed, see definition of API return values + */ +uint8_t HAND_SetID(void *ctx, uint8_t hand_id, uint8_t new_id, uint8_t *remote_err); + + +/** + * @brief Start calibration + * @note + * @param ctx: pointer to OHand context + * @param hand_id: id of OHand + * @param key: key to enable calibration, to avoid mishandling + * @param remote_err: address to put remote node error in case of HAND_RESP_HAND_ERROR + * @retval -HAND_RESP_SUCCESS: success + * -Others: failed, see definition of API return values + */ +uint8_t HAND_Calibrate(void *ctx, uint8_t hand_id, uint16_t key, uint8_t *remote_err); + + +/** + * @brief Set calibration data + * @note + * @param ctx: pointer to OHand context + * @param hand_id: id of OHand + * @param end_pos: address of array to put end_pos + * @param start_pos: address of array to put start_pos + * @param motor_cnt: motor count, i.e., array size of end_pos[] or start_pos[] + * @param thumb_root_pos: address of array to put thumb_root_pos + * @param thumb_root_pos_cnt: count of pre-defined thumb root pos + * @param remote_err: address to put remote node error in case of HAND_RESP_HAND_ERROR + * @retval -HAND_RESP_SUCCESS: success + * -Others: failed, see definition of API return values + */ +uint8_t HAND_SetCaliData(void *ctx, uint8_t hand_id, uint16_t *end_pos, uint16_t *start_pos, uint8_t motor_cnt, uint16_t *thumb_root_pos, uint8_t thumb_root_pos_cnt, uint8_t *remote_err); + + +/** + * @brief Set PID gain + * @note + * @param ctx: pointer to OHand context + * @param hand_id: id of OHand + * @param finger_id: index of finger + * @param p: PID gain p + * @param i: PID gain i + * @param d: PID gain d + * @param d: PID gain g + * @param remote_err: address to put remote node error in case of HAND_RESP_HAND_ERROR + * @retval -HAND_RESP_SUCCESS: success + * -Others: failed, see definition of API return values + */ +uint8_t HAND_SetFingerPID(void *ctx, uint8_t hand_id, uint8_t finger_id, float p, float i, float d, float g, uint8_t *remote_err); + + +/** + * @brief Set finger current limit + * @note + * @param ctx: pointer to OHand context + * @param hand_id: id of OHand + * @param finger_id: index of finger + * @param current_limit: current limit in mA for finger + * @param remote_err: address to put remote node error in case of HAND_RESP_HAND_ERROR + * @retval -HAND_RESP_SUCCESS: success + * -Others: failed, see definition of API return values + */ +uint8_t HAND_SetFingerCurrentLimit(void *ctx, uint8_t hand_id, uint8_t finger_id, uint16_t current_limit, uint8_t *remote_err); + + +/** + * @brief Set finger normal force target + * @note + * @param ctx: pointer to OHand context + * @param hand_id: id of OHand + * @param finger_id: index of finger + * @param force_target: force target in mN for finger + * @param remote_err: address to put remote node error in case of HAND_RESP_HAND_ERROR + * @retval -HAND_RESP_SUCCESS: success + * -Others: failed, see definition of API return values + */ +uint8_t HAND_SetFingerForceTarget(void *ctx, uint8_t hand_id, uint8_t finger_id, uint16_t force_target, uint8_t *remote_err); + + +/** + * @brief Set limit of absolute position for finger + * @note + * @param ctx: pointer to OHand context + * @param hand_id: id of OHand + * @param finger_id: id of finger + * @param low_limit: low limit of absolute position + * @param high_limit: high limit of absolute position + * @param remote_err: address to put remote node error in case of HAND_RESP_HAND_ERROR + * @retval -HAND_RESP_SUCCESS: success + * -Others: failed, see definition of API return values + */ +uint8_t HAND_SetFingerPosLimit(void *ctx, uint8_t hand_id, uint8_t finger_id, uint16_t low_limit, uint16_t high_limit, uint8_t *remote_err); + + +/** + * @brief Start finger in case of stuck. + * @note Fingers will auto start after about 500ms when stuck. + * @param ctx: pointer to OHand context + * @param hand_id: id of OHand + * @param finger_id_bits: bits of fingers to start + * @param remote_err: address to put remote node error in case of HAND_RESP_HAND_ERROR + * @retval -HAND_RESP_SUCCESS: success + * -Others: failed, see definition of API return values + */ +uint8_t HAND_FingerStart(void *ctx, uint8_t hand_id, uint8_t finger_id_bits, uint8_t *remote_err); + + +/** + * @brief Stop finger + * @note + * @param ctx: pointer to OHand context + * @param hand_id: id of OHand + * @param finger_id_bits: bits of fingers to stop + * @param remote_err: address to put remote node error in case of HAND_RESP_HAND_ERROR + * @retval -HAND_RESP_SUCCESS: success + * -Others: failed, see definition of API return values + */ +uint8_t HAND_FingerStop(void *ctx, uint8_t hand_id, uint8_t finger_id_bits, uint8_t *remote_err); + + +/** + * @brief Set absolute position for finger + * @note + * @param ctx: pointer to OHand context + * @param hand_id: id of OHand + * @param finger_id: id of finger + * @param raw_pos: raw position of finger + * @param speed: moving speed, [0, 255], 255 means move full range in 1 second + * @param remote_err: address to put remote node error in case of HAND_RESP_HAND_ERROR + * @retval -HAND_RESP_SUCCESS: success + * -Others: failed, see definition of API return values + */ +uint8_t HAND_SetFingerPosAbs(void *ctx, uint8_t hand_id, uint8_t finger_id, uint16_t raw_pos, uint8_t speed, uint8_t *remote_err); + + +/** + * @brief Move finger to position + * @note + * @param ctx: pointer to OHand context + * @param hand_id: id of OHand + * @param finger_id: index of finger to move + * @param pos: target position, [0, 65535], mapped to [low_limit, high_limit] internally + * @param speed: moving speed, [0, 255], 255 means move full range in 1s (0.7s for thumb root) + * @param remote_err: address to put remote node error in case of HAND_RESP_HAND_ERROR + * @retval -HAND_RESP_SUCCESS: success + * -Others: failed, see definition of API return values + */ +uint8_t HAND_SetFingerPos(void *ctx, uint8_t hand_id, uint8_t finger_id, uint16_t pos, uint8_t speed, uint8_t *remote_err); + +/** + * @brief Set finger angle + * @note + * @param ctx: pointer to OHand context + * @param hand_id: id of OHand + * @param finger_id: index of finger to move + * @param angle: target angle, value = real angle * 100 + * @param speed: moving speed, [0, 255], 255 means move full range in 1s (0.7s for thumb root) + * @param remote_err: address to put remote node error in case of HAND_RESP_HAND_ERROR + * @retval -HAND_RESP_SUCCESS: success + * -Others: failed, see definition of API return values + */ +uint8_t HAND_SetFingerAngle(void *ctx, uint8_t hand_id, uint8_t finger_id, int16_t angle, uint8_t speed, uint8_t *remote_err); + + +/** + * @brief Set thumb root pos + * @note + * @param ctx: pointer to OHand context + * @param hand_id: id of OHand + * @param pos: 0, 1 or 2 + * @param speed: moving speed, [0, 255], 255 means move full range in 0.7s + * @param remote_err: address to put remote node error in case of HAND_RESP_HAND_ERROR + * @retval -HAND_RESP_SUCCESS: success + * -Others: failed, see definition of API return values + */ +uint8_t HAND_SetThumbRootPos(void *ctx, uint8_t hand_id, uint8_t pos, uint8_t speed, uint8_t *remote_err); + + +/** + * @brief Set absolute positions for all fingers + * @note + * @param ctx: pointer to OHand context + * @param hand_id: id of OHand + * @param raw_pos: raw position of finger + * @param speed: moving speed, [0, 255], 255 means move full range in 1 second + * @param motor_cnt: motor count, i.e., array size of raw_pos[] or speed[] + * @param remote_err: address to put remote node error in case of HAND_RESP_HAND_ERROR + * @retval -HAND_RESP_SUCCESS: success + * -Others: failed, see definition of API return values + */ +uint8_t HAND_SetFingerPosAbsAll(void *ctx, uint8_t hand_id, uint16_t *raw_pos, uint8_t *speed, uint8_t motor_cnt, uint8_t *remote_err); + + +/** + * @brief Move all fingers to specified position + * @note + * @param ctx: pointer to OHand context + * @param hand_id: id of OHand + * @param pos: target position, [0, 65535], mapped to [low_limit, high_limit] internally + * @param speed: moving speed, [0, 255], 255 means move full range in 1 second + * @param motor_cnt: motor count, i.e., array size of pos[] or speed[] + * @param remote_err: address to put remote node error in case of HAND_RESP_HAND_ERROR + * @retval -HAND_RESP_SUCCESS: success + * -Others: failed, see definition of API return values + */ +uint8_t HAND_SetFingerPosAll(void *ctx, uint8_t hand_id, uint16_t *pos, uint8_t *speed, uint8_t motor_cnt, uint8_t *remote_err); + + +/** + * @brief Set first joint angles for all fingers + * @note + * @param ctx: pointer to OHand context + * @param hand_id: id of OHand + * @param angle: target angle, value = real angle * 100 + * @param speed: moving speed, [0, 255], 255 means move full range in 1 second + * @param motor_cnt: motor count, i.e., array size of angle[] or speed[] + * @param remote_err: address to put remote node error in case of HAND_RESP_HAND_ERROR + * @retval -HAND_RESP_SUCCESS: success + * -Others: failed, see definition of API return values + */ +uint8_t HAND_SetFingerAngleAll(void *ctx, uint8_t hand_id, int16_t *angle, uint8_t *speed, uint8_t motor_cnt, uint8_t *remote_err); + + +/** + * @brief Custom command + * @note + * @param ctx: pointer to OHand context + * @param hand_id: id of OHand + * @param data: address of data + * @param send_data_size: send data size + * @param recv_data_size: address of recv data size + * @param remote_err: address to put remote node error in case of HAND_RESP_HAND_ERROR + * @retval -HAND_RESP_SUCCESS: success + * -Others: failed, see definition of API return values + */ +uint8_t HAND_SetCustom(void *ctx, uint8_t hand_id, uint8_t* data, uint8_t send_data_size, uint8_t *recv_data_size, uint8_t *remote_err); + + +/** + * @brief Set self-test level + * @note + * @param ctx: pointer to OHand context + * @param hand_id: id of OHand + * @param self_test_level: self-test level, 0: wait for command HAND_CMD_START_INIT to init; 1: semi self-test on power up; 2: full self-test on power up + * @param remote_err: address to put remote node error in case of HAND_RESP_HAND_ERROR + * @retval -HAND_RESP_SUCCESS: success + * -Others: failed, see definition of API return values + */ +uint8_t HAND_SetSelfTestLevel(void *ctx, uint8_t hand_id, uint8_t self_test_level, uint8_t *remote_err); + + +/** + * @brief Set beep ON/OFF + * @note + * @param ctx: pointer to OHand context + * @param hand_id: id of OHand + * @param beep_on: beep on/off + * @param remote_err: address to put remote node error in case of HAND_RESP_HAND_ERROR + * @retval -HAND_RESP_SUCCESS: success + * -Others: failed, see definition of API return values + */ +uint8_t HAND_SetBeepSwitch(void *ctx, uint8_t hand_id, uint8_t beep_on, uint8_t *remote_err); + + +/** + * @brief Beep + * @note + * @param ctx: pointer to OHand context + * @param hand_id: id of OHand + * @param duration: beep duration in milliseconds + * @param remote_err: address to put remote node error in case of HAND_RESP_HAND_ERROR + * @retval -HAND_RESP_SUCCESS: success + * -Others: failed, see definition of API return values + */ +uint8_t HAND_Beep(void *ctx, uint8_t hand_id, uint16_t duration, uint8_t *remote_err); + + +/** + * @brief Set button pressed count, usually used when calibrating robotic hand + * @note + * @param ctx: pointer to OHand context + * @param hand_id: id of OHand + * @param pressed_cnt: button pressed count + * @param remote_err: address to put remote node error in case of HAND_RESP_HAND_ERROR + * @retval -HAND_RESP_SUCCESS: success + * -Others: failed, see definition of API return values + */ +uint8_t HAND_SetButtonPressedCnt(void *ctx, uint8_t hand_id, uint8_t pressed_cnt, uint8_t *remote_err); + + + /** + * @brief Start init in case of SELF_TEST_SWITCH=0 + * @note + * @param ctx: pointer to OHand context + * @param hand_id: id of OHand + * @param remote_err: address to put remote node error in case of HAND_RESP_HAND_ERROR + * @retval -HAND_RESP_SUCCESS: success + * -Others: failed, see definition of API return values + */ +uint8_t HAND_StartInit(void *ctx, uint8_t hand_id, uint8_t *remote_err); + + + /** + * @brief Set manufacture data + * @note + * @param ctx: pointer to OHand context + * @param hand_id: id of OHand + * @param data: address of data + * @param data_size: data size + * @param remote_err: address to put remote node error in case of HAND_RESP_HAND_ERROR + * @retval -HAND_RESP_SUCCESS: success + * -Others: failed, see definition of API return values + */ +uint8_t HAND_SetManufactureData(void *ctx, uint8_t hand_id, uint8_t *data, uint8_t data_size, uint8_t *remote_err); + + +/** + * @brief Set force PID for specific finger + * @note + * @param ctx: pointer to OHand context + * @param hand_id: id of OHand + * @param finger_id: index of finger + * @param p: PID gain p + * @param i: PID gain i + * @param d: PID gain d + * @param d: PID gain g + * @param remote_err: address to put remote node error in case of HAND_RESP_HAND_ERROR + * @retval -HAND_RESP_SUCCESS: success + * -Others: failed, see definition of API return values + */ +uint8_t HAND_SetFingerForcePID(void *ctx, uint8_t hand_id, uint8_t finger_id, float p, float i, float d, float g, uint8_t *remote_err); + +/** + * @brief Set Stop Parameter + * @note + * @param hand_id: id of OHand + * @param finger_id: index of finger + * @param speed: address of var to put Stop Parameter speed + * @param current: address of var to put Stop Parameter current + * @param after_period: address of var to put Stop Parameter after_period + * @param retry_period: address of var to put Stop Parameter retry_period + * @retval -RESP_SUCCESS: success + * -Others: failed, see definition of API return values + */ +uint8_t HAND_SetFingerStopParam(void *ctx, uint8_t hand_id, uint8_t finger_id, uint16_t speed, uint16_t current, uint16_t after_period, uint16_t retry_period, uint8_t *remote_err); + + +/** + * @brief Set Speed Control Parameters of finger + * @note + * @param hand_id: id of OHand + * @param brake_distance: Speed Brake Distance + * @param accel_distance: Speed Accelerate Distance + * @param speed_ratio: PID Speed Ratio + * @retval -RESP_SUCCESS: success + * -Others: failed, see definition of API return values + */ +uint8_t HAND_SetFingerSpeedCtrlParams(void *ctx, uint8_t hand_id, uint16_t brake_distance, uint16_t accel_distance, float speed_ratio, uint8_t* remote_err); + + +/** + * @brief Reset force, that is, calibrate + * @note + * @param ctx: pointer to OHand context + * @param hand_id: id of OHand + * @param remote_err: address to put remote node error in case of HAND_RESP_HAND_ERROR + * @retval -HAND_RESP_SUCCESS: success + * -Others: failed, see definition of API return values + */ +uint8_t HAND_ResetForce(void *ctx, uint8_t hand_id, uint8_t *remote_err); + +#ifdef __cplusplus +} +#endif +#endif //__HAND_SERIAL_API_H__ diff --git a/dependency/x86/third_party/ohand_serial_sdk/lib/libROHSerialAPIStatic.a b/dependency/x86/third_party/ohand_serial_sdk/lib/libROHSerialAPIStatic.a new file mode 100644 index 0000000000000000000000000000000000000000..8d805a5aaeb3bcb5fd81fb5b696d30ba5130b222 GIT binary patch literal 41154 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 literal 0 HcmV?d00001 diff --git a/protos/cmvr/config/dexhand_config/dexhand_config.proto b/protos/cmvr/config/dexhand_config/dexhand_config.proto index 1568aa3e..210d1801 100644 --- a/protos/cmvr/config/dexhand_config/dexhand_config.proto +++ b/protos/cmvr/config/dexhand_config/dexhand_config.proto @@ -45,6 +45,14 @@ message ZeroSimTouchDexHand { string id = 1; } +message OYMotionAP001Config { + string id = 1; + string can_interface = 2; + uint32 hand_id = 3; + uint32 master_id = 4; + uint32 command_timeout_ms = 5; +} + message DexHandDeviceConfig { @@ -55,6 +63,7 @@ message DexHandDeviceConfig { RH56DFTPDexHandConfig rh56dftp = 10; PX6AXGen3 px_6ax_gen3 = 11; ZeroSimTouchDexHand zero_sim_touch = 12; + OYMotionAP001Config oymotion_ap001 = 13; } }