Skip to content

Add support of the new power-board hardware #15

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ endif(BUILD_PYTHON_INTERFACE)

# --- MAIN LIBRARY -------------------------------------------------------------
set(ODRI_CONTROL_INTERFACE_SRC src/joint_modules.cpp src/imu.cpp src/robot.cpp
src/calibration.cpp src/utils.cpp)
src/calibration.cpp src/utils.cpp src/powerboard.cpp)
add_library(${PROJECT_NAME} SHARED ${ODRI_CONTROL_INTERFACE_SRC})
target_link_libraries(${PROJECT_NAME} yaml-cpp)
target_link_libraries(${PROJECT_NAME} master_board_sdk::master_board_sdk)
Expand Down
56 changes: 56 additions & 0 deletions include/odri_control_interface/powerboard.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/**
* @file powerboard.hpp
* @author Pierre-Alexandre Leziart ([email protected])
* license License BSD-3-Clause
* @copyright Copyright (c) 2022, New York University, Max Planck
* Gesellschaft and LAAS-CNRS
* @date 2022-04-19
*
* @brief Powerboard abstraction.
*/

#pragma once

#include <math.h>
#include <unistd.h>
#include <stdexcept>

#include "master_board_sdk/defines.h"
#include "master_board_sdk/master_board_interface.h"

#include <odri_control_interface/common.hpp>

namespace odri_control_interface
{
/**
* @brief Class for dealing with the powerboard.
*/
class Powerboard
{
protected:
std::shared_ptr<MasterBoardInterface> robot_if_;

// Cache for the results.
double current_;
double voltage_;
double energy_;

public:
Powerboard(const std::shared_ptr<MasterBoardInterface>& robot_if);

// If needed, add some error handling for the powerboard as well.
// For instance, check for low voltage or high current
bool HasError()
{
return false;
}

void ParseSensorData();

const std::shared_ptr<MasterBoardInterface>& GetMasterBoardInterface();
double GetCurrent();
double GetVoltage();
double GetEnergy();
};

} // namespace odri_control_interface
8 changes: 8 additions & 0 deletions include/odri_control_interface/robot.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include <odri_control_interface/calibration.hpp>
#include <odri_control_interface/imu.hpp>
#include <odri_control_interface/joint_modules.hpp>
#include <odri_control_interface/powerboard.hpp>

namespace odri_control_interface
{
Expand All @@ -31,6 +32,7 @@ class Robot
std::shared_ptr<MasterBoardInterface> robot_if;
std::shared_ptr<JointModules> joints;
std::shared_ptr<IMU> imu;
std::shared_ptr<Powerboard> powerboard;
std::shared_ptr<JointCalibrator> calibrator;

protected:
Expand All @@ -43,6 +45,7 @@ class Robot
Robot(const std::shared_ptr<MasterBoardInterface>& robot_if,
const std::shared_ptr<JointModules>& joint_modules,
const std::shared_ptr<IMU>& imu,
const std::shared_ptr<Powerboard>& powerboard,
const std::shared_ptr<JointCalibrator>& calibrator);

/**
Expand All @@ -60,6 +63,11 @@ class Robot
*/
const std::shared_ptr<IMU>& GetIMU();

/**
* @brief Return the powerboard.
*/
const std::shared_ptr<Powerboard>& GetPowerboard();

/**
* @brief Initializes the connection. Use `SendInit` to initialize the
* session.
Expand Down
50 changes: 50 additions & 0 deletions src/powerboard.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/**
* @file powerboard.hpp
* @author Pierre-Alexandre Leziart ([email protected])
* license License BSD-3-Clause
* @copyright Copyright (c) 2020, New York University and Max Planck
* Gesellschaft.
* @date 2021-08-23
*
* @brief Powerboard abstraction.
*/

#include "odri_control_interface/powerboard.hpp"

#include <iostream>

namespace odri_control_interface
{
Powerboard::Powerboard(const std::shared_ptr<MasterBoardInterface>& robot_if)
: robot_if_(robot_if)
{
}

const std::shared_ptr<MasterBoardInterface>& Powerboard::GetMasterBoardInterface()
{
return robot_if_;
}

double Powerboard::GetCurrent()
{
return current_;
}

double Powerboard::GetVoltage()
{
return voltage_;
}

double Powerboard::GetEnergy()
{
return energy_;
}

void Powerboard::ParseSensorData()
{
current_ = robot_if_->powerboard_current();
voltage_ = robot_if_->powerboard_voltage();
energy_ = robot_if_->powerboard_energy();
}

} // namespace odri_control_interface
16 changes: 15 additions & 1 deletion src/robot.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,10 @@ namespace odri_control_interface
Robot::Robot(const std::shared_ptr<MasterBoardInterface>& robot_if,
const std::shared_ptr<JointModules>& joint_modules,
const std::shared_ptr<IMU>& imu,
const std::shared_ptr<Powerboard>& powerboard,
const std::shared_ptr<JointCalibrator>& calibrator)
: robot_if(robot_if), joints(joint_modules), imu(imu),
calibrator(calibrator), timeout_counter_(0), saw_error_(false)
powerboard(powerboard), calibrator(calibrator), timeout_counter_(0), saw_error_(false)
{
last_time_ = std::chrono::system_clock::now();
}
Expand All @@ -40,6 +41,11 @@ const std::shared_ptr<IMU>& Robot::GetIMU()
return imu;
}

const std::shared_ptr<Powerboard>& Robot::GetPowerboard()
{
return powerboard;
}

void Robot::Init()
{
// Init the robot.
Expand Down Expand Up @@ -137,6 +143,10 @@ void Robot::ParseSensorData()
{
imu->ParseSensorData();
}
if (powerboard)
{
powerboard->ParseSensorData();
}
}

bool Robot::RunCalibration(const std::shared_ptr<JointCalibrator>& calibrator,
Expand Down Expand Up @@ -264,6 +274,10 @@ bool Robot::HasError()
{
saw_error_ |= imu->HasError();
}
if (powerboard)
{
saw_error_ |= powerboard->HasError();
}

if (robot_if->IsTimeout())
{
Expand Down
11 changes: 8 additions & 3 deletions src/utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -275,13 +275,18 @@ std::shared_ptr<Robot> RobotFromYamlFile(const std::string& if_name,
assert_yaml_parsing(robot_node, "robot", "imu");
std::shared_ptr<IMU> imu = IMUFromYaml(robot_if, robot_node["imu"]);

// 4. Create the calibrator procedure.
// 4. Create the powerboard
std::shared_ptr<Powerboard> powerboard =
std::make_shared<Powerboard>(robot_if);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This by default creates a power board. Does this make sense or should there be a flag in the yaml file to indicated if the powerboard is available on a robot or not?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At the moment, the MasterBoard protocol will include all the fields even if a power board is not present. If so the values will read 0.

This is the same with the IMU.

We could in the future have the MasterBoard to auto detect the presence of IMU, PowerBoard and number of uDrivers. According to this, the network packets could be lighten. An expected hardware description via flags in the yaml could then allow to generate an error if some components are missing.

I think this is out of the scope if this PR, and the proposed implementation is coherent with IMU.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense, thanks for the clearification.

About the master board SDK: Do we need to reflash all our master boards once the software changes to the SDK land that include the power board, even the ones that do not use a power board to get the zero values?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, all master boards will need to be updated together with the sdk.
My advice would be to flash your master board with open-dynamic-robot-initiative/master-board#107 as it's solves old issue we have.


// 5. Create the calibrator procedure.
assert_yaml_parsing(param, file_path, "joint_calibrator");
std::shared_ptr<JointCalibrator> calibrator =
JointCalibratorFromYaml(joints, param["joint_calibrator"]);

// 5. Create the robot instance from the objects.
return std::make_shared<Robot>(robot_if, joints, imu, calibrator);
// 6. Create the robot instance from the objects.
return std::make_shared<Robot>(robot_if, joints, imu,
powerboard, calibrator);
}

std::shared_ptr<Robot> RobotFromYamlFile(const std::string& file_path)
Expand Down
17 changes: 17 additions & 0 deletions srcpy/bindings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,18 @@ BOOST_PYTHON_MODULE(libodri_control_interface_pywrap)
return_value_policy<copy_const_reference>()));
register_ptr_to_python<std::shared_ptr<IMU>>();

// Powerboard bindings and it's std::shared_ptr.
class_<Powerboard>("Powerboard", init<std::shared_ptr<MasterBoardInterface>>())
.add_property("has_error", &Powerboard::HasError)
.add_property(
"robot_interface",
make_function(&Powerboard::GetMasterBoardInterface,
return_value_policy<copy_const_reference>()))
.add_property("current", &Powerboard::GetCurrent)
.add_property("voltage", &Powerboard::GetVoltage)
.add_property("energy", &Powerboard::GetEnergy);
register_ptr_to_python<std::shared_ptr<Powerboard>>();

// CalibrationMethod enum bindings.
enum_<CalibrationMethod>("CalibrationMethod")
.value("auto", CalibrationMethod::AUTO)
Expand All @@ -220,6 +232,7 @@ BOOST_PYTHON_MODULE(libodri_control_interface_pywrap)
init<std::shared_ptr<MasterBoardInterface>,
std::shared_ptr<JointModules>,
std::shared_ptr<IMU>,
std::shared_ptr<Powerboard>,
std::shared_ptr<JointCalibrator>>())
.def("init", &Robot::Init)
.def("sendInit", &Robot::SendInit)
Expand All @@ -246,6 +259,10 @@ BOOST_PYTHON_MODULE(libodri_control_interface_pywrap)
"imu",
make_function(&Robot::GetIMU,
return_value_policy<copy_const_reference>()))
.add_property(
"powerboard",
make_function(&Robot::GetPowerboard,
return_value_policy<copy_const_reference>()))
.add_property("is_ready", &Robot::IsReady)
.add_property("is_timeout", &Robot::IsTimeout)
.add_property("is_ack_msg_received", &Robot::IsAckMsgReceived)
Expand Down