Skip to content

/home/runner/work/dynamixel_hardware_interface/dynamixel_hardware_interface/src/dynamixel_hardware_interface.cpp#

Class implementation of the hardware interface for the Dynamixel motor. More...

Namespaces#

Name
dynamixel_hardware_interface

Detailed Description#

Class implementation of the hardware interface for the Dynamixel motor.

Author: Masaya Kataoka (ms.kataoka@gmail.com)

Version: 0.1

Date: 2021-05-01

Copyright: Copyright (c) OUXT Polaris 2021

Source code#

// Copyright (c) 2021 OUXT Polaris
//
// 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.

#include <dynamixel_hardware_interface/dynamixel_hardware_interface.hpp>
#include <memory>
#include <string>
#include <vector>

namespace dynamixel_hardware_interface
{
#if defined(GALACTIC) || defined(HUMBLE)
rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn
DynamixelHardwareInterface::on_init(const hardware_interface::HardwareInfo & info)
#else
hardware_interface::return_type DynamixelHardwareInterface::configure(
  const hardware_interface::HardwareInfo & info)
#endif
{
#if defined(GALACTIC) || defined(HUMBLE)
  if (
    SystemInterface::on_init(info) !=
    rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn::SUCCESS) {
    return rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn::ERROR;
  }
#else
  if (configure_default(info) != hardware_interface::return_type::OK) {
    return hardware_interface::return_type::ERROR;
  }
#endif
  RCLCPP_INFO_STREAM(
    rclcpp::get_logger("dynamixel_hardware_interface"), "configure hardware " << info.name);
  for (const auto & hardware_parameter : info_.hardware_parameters) {
    RCLCPP_INFO_STREAM(
      rclcpp::get_logger("dynamixel_hardware_interface"),
      "hardware parameter : " << hardware_parameter.first << " = " << hardware_parameter.second);
  }
  port_name_ = getHardwareParameter<std::string>("port_name");
  baudrate_ = getHardwareParameter<int>("baudrate");
  RCLCPP_INFO(rclcpp::get_logger("dynamixel_hardware_interface"), "initialize port handler");
  port_handler_ = std::shared_ptr<dynamixel::PortHandler>(
    dynamixel::PortHandler::getPortHandler(port_name_.c_str()));
  port_handler_->setBaudRate(baudrate_);
  RCLCPP_INFO(rclcpp::get_logger("dynamixel_hardware_interface"), "initialize packet handler");
  packet_handler_ = std::shared_ptr<dynamixel::PacketHandler>(
    dynamixel::PacketHandler::getPacketHandler(PROTOCOL_VERSION));
  if (!getHardwareParameter<bool>("enable_dummy")) {
    RCLCPP_INFO_STREAM(
      rclcpp::get_logger("dynamixel_hardware_interface"),
      "serial port : " << port_handler_->getPortName());
    RCLCPP_INFO_STREAM(
      rclcpp::get_logger("dynamixel_hardware_interface"),
      "baudrate : " << port_handler_->getBaudRate());
    if (port_handler_->openPort()) {
      RCLCPP_INFO(rclcpp::get_logger("dynamixel_hardware_interface"), "open serial port succeed");
    } else {
      RCLCPP_ERROR(rclcpp::get_logger("dynamixel_hardware_interface"), "open serial port failed");
#if defined(GALACTIC) || defined(HUMBLE)
      return rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn::ERROR;
#else
      return hardware_interface::return_type::ERROR;
#endif
    }
  }
  RCLCPP_INFO(rclcpp::get_logger("dynamixel_hardware_interface"), "configure each motors");
  for (const auto & joint : info.joints) {
    std::shared_ptr<MotorBase> motor;
    try {
      motor = constructMotorInstance(joint);
    } catch (const std::runtime_error & e) {
      RCLCPP_ERROR_STREAM(rclcpp::get_logger("dynamixel_hardware_interface"), e.what());
#if defined(GALACTIC) || defined(HUMBLE)
      return rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn::ERROR;
#else
      return hardware_interface::return_type::ERROR;
#endif
    }
    const auto result = motor->configure();
    if (!result.success) {
      RCLCPP_ERROR_STREAM(rclcpp::get_logger("dynamixel_hardware_interface"), result.description);
#if defined(GALACTIC) || defined(HUMBLE)
      return rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn::ERROR;
#else
      return hardware_interface::return_type::ERROR;
#endif
    }
    motors_.emplace_back(motor);
  }
#if defined(GALACTIC) || defined(HUMBLE)
  return rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn::SUCCESS;
#else
  return hardware_interface::return_type::OK;
#endif
}

std::vector<hardware_interface::StateInterface>
DynamixelHardwareInterface::export_state_interfaces()
{
  std::vector<hardware_interface::StateInterface> state_interfaces = {};
  for (const auto & motor : motors_) {
    motor->appendStateInterfaces(state_interfaces);
  }
  RCLCPP_INFO_STREAM(
    rclcpp::get_logger("dynamixel_hardware_interface"), state_interfaces.size()
                                                          << " state interfaces exported.");
  return state_interfaces;
}

std::vector<hardware_interface::CommandInterface>
DynamixelHardwareInterface::export_command_interfaces()
{
  std::vector<hardware_interface::CommandInterface> command_interfaces = {};
  for (const auto & motor : motors_) {
    motor->appendCommandInterfaces(command_interfaces);
  }
  RCLCPP_INFO_STREAM(
    rclcpp::get_logger("dynamixel_hardware_interface"), command_interfaces.size()
                                                          << " command interfaces exported.");
  return command_interfaces;
}

SupportedMotors DynamixelHardwareInterface::strToSupportMotorsEnum(
  const std::string & motor_type) const
{
  if (motor_type == "XW540-T260") {
    return SupportedMotors::XW540_T260;
  }
  return SupportedMotors::INVALID;
}

std::shared_ptr<MotorBase> DynamixelHardwareInterface::constructMotorInstance(
  const hardware_interface::ComponentInfo & info) const
{
  RCLCPP_INFO_STREAM(
    rclcpp::get_logger("dynamixel_hardware_interface"),
    "constructing motor instance : " << info.name);
  for (const auto & parameter : info.parameters) {
    RCLCPP_INFO_STREAM(
      rclcpp::get_logger("dynamixel_hardware_interface"),
      "parameter " << parameter.first << " : " << parameter.second);
  }
  if (info.type == "joint") {
    const auto motor_type = strToSupportMotorsEnum(getParameter<std::string>("motor_type", info));
    if (motor_type == SupportedMotors::INVALID) {
      throw std::runtime_error("failed to construct motor instance, motor type is invalid");
    }
    const auto id = static_cast<uint8_t>(getParameter<int>("id", info));

    const auto max_joint_limit = getParameter<double>("max_joint_limit", info);
    const auto min_joint_limit = getParameter<double>("min_joint_limit", info);

    switch (motor_type) {
      case SupportedMotors::XW540_T260:
        return std::make_shared<motors::XW540_T260>(
          info.name, getHardwareParameter<bool>("enable_dummy"), baudrate_, id, max_joint_limit,
          min_joint_limit, port_handler_, packet_handler_);
        break;
      default:
        break;
    }
  }
  throw std::runtime_error("failed to construct motor instance");
}

// #ifndef GALACTIC
// hardware_interface::return_type DynamixelHardwareInterface::start()
// {
//   status_ = hardware_interface::status::STARTED;
//   return hardware_interface::return_type::OK;
// }

// hardware_interface::return_type DynamixelHardwareInterface::stop()
// {
//   return hardware_interface::return_type::OK;
// }
// #endif

hardware_interface::return_type DynamixelHardwareInterface::read(
  const rclcpp::Time & /*time*/, const rclcpp::Duration & /*period*/)
{
  for (const auto & motor : motors_) {
    if (motor->operationSupports(Operation::PRESENT_POSITION)) {
      const auto result = motor->updateJointPosition();
      if (!result.success) {
        RCLCPP_ERROR_STREAM(rclcpp::get_logger("dynamixel_hardware_interface"), result.description);
        return hardware_interface::return_type::ERROR;
      }
    }
    if (motor->operationSupports(Operation::PRESENT_SPEED)) {
      const auto result = motor->updateJointVelocity();
      if (!result.success) {
        RCLCPP_ERROR_STREAM(rclcpp::get_logger("dynamixel_hardware_interface"), result.description);
        return hardware_interface::return_type::ERROR;
      }
    }
    if (motor->operationSupports(Operation::PRESENT_TEMPERATURE)) {
      const auto result = motor->updatePresentTemperature();
      if (!result.success) {
        RCLCPP_ERROR_STREAM(rclcpp::get_logger("dynamixel_hardware_interface"), result.description);
        return hardware_interface::return_type::ERROR;
      }
    }
  }
  return hardware_interface::return_type::OK;
}

hardware_interface::return_type DynamixelHardwareInterface::write(
  const rclcpp::Time & /*time*/, const rclcpp::Duration & /*period*/)
{
  for (const auto & motor : motors_) {
    if (motor->operationSupports(Operation::GOAL_POSITION)) {
      motor->setCurrentGoalPosition();
    }
  }
  return hardware_interface::return_type::OK;
}
}  // namespace dynamixel_hardware_interface

#include "pluginlib/class_list_macros.hpp"

PLUGINLIB_EXPORT_CLASS(
  dynamixel_hardware_interface::DynamixelHardwareInterface, hardware_interface::SystemInterface)

Updated on 17 July 2023 at 01:42:11 UTC