Skip to content
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

Fix Haptic glove transmission - GloveDevice #204

Merged
merged 15 commits into from
Jun 25, 2024
Merged
Show file tree
Hide file tree
Changes from 9 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: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,5 @@ CMakeLists.txt.*
*.autosave
*.original
*.*~
.vscode/c_cpp_properties.json
.vscode/settings.json
12 changes: 6 additions & 6 deletions devices/HapticGlove/conf/HapticGlove.xml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
</device>

<device type="iwear_wrapper" name="LeftHapticGloveWearableDeviceWrapper">
<param extern-name="period" name="period">0.01</param>
<param extern-name="period" name="period">0.1</param>
<param name="dataPortName">/WearableData/HapticGlove/LeftHand/data:o</param>
<param name="rpcPortName">/WearableData/HapticGlove/LeftHand/metadataRpc:o</param>
<action phase="startup" level="5" type="attach">
Expand All @@ -29,8 +29,8 @@
</device>

<device type="iwearactuators_wrapper" name="LeftHapticGloveWearableDeviceActuatorsWrapper">
<param extern-name="period" name="period">0.01</param>
<param name="actuatorCommandInputPortName">/WearableData/HapticGlove/LeftHand/Actuators/input:i</param>
<param extern-name="period" name="period">0.1</param>
<param name="gloveActuatorCommandInputPortName">/WearableData/HapticGlove/LeftHand/Actuators/input:i</param>
<action phase="startup" level="5" type="attach">
<paramlist name="networks">
<elem name="HapticGloveWearableDeviceActuatorWrapperLabel"> LeftHapticGloveWearableDevice </elem>
Expand All @@ -53,7 +53,7 @@
</device>

<device type="iwear_wrapper" name="RightHapticGloveWearableDeviceWrapper">
<param extern-name="period" name="period">0.01</param>
<param extern-name="period" name="period">0.1</param>
<param name="dataPortName">/WearableData/HapticGlove/RightHand/data:o</param>
<param name="rpcPortName">/WearableData/HapticGlove/RightHand/metadataRpc:o</param>
<action phase="startup" level="5" type="attach">
Expand All @@ -65,8 +65,8 @@
</device>

<device type="iwearactuators_wrapper" name="RightHapticGloveWearableDeviceActuatorsWrapper">
<param extern-name="period" name="period">0.01</param>
<param name="actuatorCommandInputPortName">/WearableData/HapticGlove/RightHand/Actuators/input:i</param>
<param extern-name="period" name="period">0.1</param>
<param name="gloveActuatorCommandInputPortName">/WearableData/HapticGlove/RightHand/Actuators/input:i</param>
<action phase="startup" level="5" type="attach">
<paramlist name="networks">
<elem name="HapticGloveWearableDeviceActuatorWrapperLabel"> RightHapticGloveWearableDevice </elem>
Expand Down
33 changes: 25 additions & 8 deletions devices/HapticGlove/src/HapticGlove.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,14 @@ bool HapticGlove::open(yarp::os::Searchable& config)

m_pImpl->hapticActuatorPrefix = getWearableName() + actuator::IHaptic::getPrefix();

for (size_t i = 0; i < m_pImpl->gloveData.humanFingerNames.size(); i++) {
m_pImpl->sensegloveHapticActuatorVector.push_back(
std::make_shared<SenseGloveImpl::SenseGloveHapticActuator>(
m_pImpl.get(),
EhsanRanjbari marked this conversation as resolved.
Show resolved Hide resolved
m_pImpl->hapticActuatorPrefix
+ "HapticFeedback"));
}

for (size_t i = 0; i < m_pImpl->gloveData.humanFingerNames.size(); i++) {
m_pImpl->sensegloveHapticActuatorVector.push_back(
std::make_shared<SenseGloveImpl::SenseGloveHapticActuator>(
Expand Down Expand Up @@ -339,6 +347,12 @@ bool HapticGlove::open(yarp::os::Searchable& config)
m_pImpl->gloveData.humanJointSensorNameIdMap.emplace(
std::make_pair(m_pImpl->jointSensorPrefix + m_pImpl->gloveData.humanJointNames[i], i));

for (size_t i = 0; i < m_pImpl->gloveData.humanFingerNames.size(); i++)
m_pImpl->gloveData.humanHapticActuatorNameIdMap.emplace(
std::make_pair(m_pImpl->hapticActuatorPrefix
+ "HapticFeedback",
i));

for (size_t i = 0; i < m_pImpl->gloveData.humanFingerNames.size(); i++)
m_pImpl->gloveData.humanHapticActuatorNameIdMap.emplace(
std::make_pair(m_pImpl->hapticActuatorPrefix + m_pImpl->gloveData.humanFingerNames[i]
Expand Down Expand Up @@ -537,22 +551,25 @@ class HapticGlove::SenseGloveImpl::SenseGloveHapticActuator : public wearable::a

bool setHapticCommand(double& value) const override
{
yError() << LogPrefix << "Wrong method has been called! To set the haptic command please use the setHapticsCommand method.";
return false;
}
S-Dafarra marked this conversation as resolved.
Show resolved Hide resolved

std::lock_guard<std::mutex> lock(m_gloveImpl->mutex);
bool setHapticsCommand(std::vector<double>& forceValue, std::vector<double>& vibrotactileValue) const override
{

if (!m_gloveImpl->isAvailable(m_actuatorName,
m_gloveImpl->gloveData.humanHapticActuatorNameIdMap)) {
yError() << LogPrefix << "The actuator name (" << m_actuatorName
<< ") is not found in the list of actuators.";
std::lock_guard<std::mutex> lock(m_gloveImpl->mutex);

return false;
for (size_t i = 0; i < m_gloveImpl->nFingers; i++)
{
m_gloveImpl->gloveData.fingersHapticFeedback[i] = forceValue[i];
m_gloveImpl->gloveData.fingersHapticFeedback[i + 5] = vibrotactileValue[i];
EhsanRanjbari marked this conversation as resolved.
Show resolved Hide resolved
S-Dafarra marked this conversation as resolved.
Show resolved Hide resolved
}
m_gloveImpl->gloveData.fingersHapticFeedback
[m_gloveImpl->gloveData.humanHapticActuatorNameIdMap[m_actuatorName]] = value;

return true;
}


inline void setStatus(const actuator::ActuatorStatus& status) { m_status = status; }

private:
Expand Down
2 changes: 2 additions & 0 deletions interfaces/IWear/include/Wearable/IWear/Actuators/IHaptic.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ class wearable::actuator::IHaptic : public wearable::actuator::IActuator
inline static const std::string getPrefix();

virtual bool setHapticCommand(double& value) const = 0;

virtual bool setHapticsCommand(std::vector<double>& forceValue, std::vector<double>& vibrotactileValue) const = 0;
EhsanRanjbari marked this conversation as resolved.
Show resolved Hide resolved
};

inline const std::string wearable::actuator::IHaptic::getPrefix()
Expand Down
10 changes: 10 additions & 0 deletions msgs/thrift/WearableActuators.thrift
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,13 @@ struct WearableActuatorCommand {
2: double value;
3: double duration;
}

// ==========================
// Glove Actuator Command data type
// ==========================

struct GloveActuatorCommand {
1: ActuatorInfo info;
2: list<double> forceValue;
3: list<double> vibroTactileValue;
}
3 changes: 3 additions & 0 deletions wrappers/IWearActuators/include/IWearActuatorsWrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <yarp/os/TypedReaderCallback.h>

#include "thrift/WearableActuatorCommand.h"
#include "thrift/GloveActuatorCommand.h"

namespace wearable {
namespace wrappers {
Expand All @@ -25,6 +26,7 @@ class wearable::wrappers::IWearActuatorsWrapper
, public yarp::dev::IMultipleWrapper
, public yarp::os::PeriodicThread
, public yarp::os::TypedReaderCallback<msg::WearableActuatorCommand>
, public yarp::os::TypedReaderCallback<msg::GloveActuatorCommand>
{
private:
class impl;
Expand All @@ -40,6 +42,7 @@ class wearable::wrappers::IWearActuatorsWrapper

// TypedReaderCallback
void onRead(msg::WearableActuatorCommand& wearableActuatorCommand) override;
void onRead(msg::GloveActuatorCommand& gloveActuatorCommand) override;

// PeriodicThread
void run() override;
Expand Down
52 changes: 52 additions & 0 deletions wrappers/IWearActuators/src/IWearActuatorsWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,14 @@ class IWearActuatorsWrapper::impl : public wearable::msg::WearableActuatorComman
std::string attachedWearableDeviceKey = "defaultIWearActuatorsWrapperDevice";

std::string actuatorCommandInputPortName;
std::string gloveActuatorCommandInputPortName;
yarp::os::BufferedPort<wearable::msg::WearableActuatorCommand> actuatorCommandInputPort;
yarp::os::BufferedPort<wearable::msg::GloveActuatorCommand> gloveActuatorCommandInputPort;

std::unordered_map<std::string, wearable::ElementPtr<const actuator::IActuator>> actuatorsMap;

msg::WearableActuatorCommand wearableActuatorCommand;
msg::GloveActuatorCommand gloveActuatorCommand;

wearable::IWear* iWear = nullptr;
};
Expand Down Expand Up @@ -59,6 +62,11 @@ bool IWearActuatorsWrapper::open(yarp::os::Searchable& config)
return false;
}

if (!config.check("gloveActuatorCommandInputPortName") || !config.find("gloveActuatorCommandInputPortName").isString()) {
yError() << LogPrefix << "gloveActuatorCommandInputPortName parameter not found";
return false;
}
S-Dafarra marked this conversation as resolved.
Show resolved Hide resolved


if (!config.check("period")) {
yInfo() << LogPrefix << "Using default period: " << DefaultPeriod << "s";
Expand All @@ -70,6 +78,7 @@ bool IWearActuatorsWrapper::open(yarp::os::Searchable& config)
setPeriod(period);

pImpl->actuatorCommandInputPortName = config.find("actuatorCommandInputPortName").asString();
pImpl->gloveActuatorCommandInputPortName = config.find("actuatorCommandInputPortName").asString();
EhsanRanjbari marked this conversation as resolved.
Show resolved Hide resolved


// Configure yarp ports
Expand All @@ -80,8 +89,15 @@ bool IWearActuatorsWrapper::open(yarp::os::Searchable& config)
return false;
}

if(!pImpl->gloveActuatorCommandInputPort.open(pImpl->gloveActuatorCommandInputPortName))
{
yError() << "Failed to open " << pImpl->gloveActuatorCommandInputPortName << " yarp port";
return false;
}

// Set the callback to use onRead() method of this device
pImpl->actuatorCommandInputPort.useCallback(*this);
pImpl->gloveActuatorCommandInputPort.useCallback(*this);
EhsanRanjbari marked this conversation as resolved.
Show resolved Hide resolved

return true;
}
Expand Down Expand Up @@ -136,6 +152,42 @@ void IWearActuatorsWrapper::onRead(msg::WearableActuatorCommand& wearableActuato
}
}

void IWearActuatorsWrapper::onRead(msg::GloveActuatorCommand& gloveActuatorCommand)
{
// Unpack the actuator in from incoming command
wearable::msg::ActuatorInfo info = gloveActuatorCommand.info;

// Check if the commanded actuator name is available
if (pImpl->actuatorsMap.find(info.name) == pImpl->actuatorsMap.end())
{
yWarning() << "Requested actuator with name " << info.name << " is not available in " << pImpl->attachedWearableDeviceKey << " wearable device \n \t Ignoring wearable actuation command.";
}
else // process the wearable actuator command
{
wearable::actuator::ActuatorType aType = pImpl->actuatorsMap[info.name]->getActuatorType();

switch (aType) {
case wearable::actuator::ActuatorType::Haptic: {

// Check if the actuator type in the wearable command is correct
if(info.type == wearable::msg::ActuatorType::HAPTIC)
{
// Get haptic actuator
wearable::ElementPtr<const wearable::actuator::IHaptic> castActuator = std::static_pointer_cast<const wearable::actuator::IHaptic>(pImpl->actuatorsMap[info.name]);

// Send haptic command
castActuator->setHapticsCommand(gloveActuatorCommand.forceValue, gloveActuatorCommand.vibroTactileValue);
}

break;
}
default: {
return;
}
}
S-Dafarra marked this conversation as resolved.
Show resolved Hide resolved
}
}

bool IWearActuatorsWrapper::close()
{
pImpl->actuatorCommandInputPort.close();
Expand Down