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

[GenericSystem] Add velocity-only mode in fake_components #540

Closed
27 changes: 27 additions & 0 deletions hardware_interface/include/fake_components/generic_system.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#ifndef FAKE_COMPONENTS__GENERIC_SYSTEM_HPP_
#define FAKE_COMPONENTS__GENERIC_SYSTEM_HPP_

#include <chrono>
#include <string>
#include <vector>

Expand All @@ -32,6 +33,13 @@ using hardware_interface::return_type;

namespace fake_components
{
enum StoppingInterface
{
NONE,
STOP_POSITION,
STOP_VELOCITY
};

Comment on lines +36 to +42
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
enum StoppingInterface
{
NONE,
STOP_POSITION,
STOP_VELOCITY
};

class HARDWARE_INTERFACE_PUBLIC GenericSystem
: public hardware_interface::BaseInterface<hardware_interface::SystemInterface>
{
Expand All @@ -58,6 +66,14 @@ class HARDWARE_INTERFACE_PUBLIC GenericSystem

return_type write() override { return return_type::OK; }

return_type prepare_command_mode_switch(
const std::vector<std::string> & start_interfaces,
const std::vector<std::string> & stop_interfaces) override;

return_type perform_command_mode_switch(
const std::vector<std::string> & start_interfaces,
const std::vector<std::string> & stop_interfaces) override;

protected:
/// Use standard interfaces for joints because they are relevant for dynamic behaviour
/**
Expand All @@ -71,6 +87,7 @@ class HARDWARE_INTERFACE_PUBLIC GenericSystem
hardware_interface::HW_IF_ACCELERATION, hardware_interface::HW_IF_EFFORT};

const size_t POSITION_INTERFACE_INDEX = 0;
const size_t VELOCITY_INTERFACE_INDEX = 1;

struct MimicJoint
{
Expand Down Expand Up @@ -109,6 +126,16 @@ class HARDWARE_INTERFACE_PUBLIC GenericSystem
double position_state_following_offset_;
std::string custom_interface_with_following_offset_;
size_t index_custom_interface_with_following_offset_;
bool command_propagation_disabled_;

// resources switching aux vars
std::vector<uint> stop_modes_;
std::vector<std::string> start_modes_;
Comment on lines +132 to +133
Copy link
Member

Choose a reason for hiding this comment

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

I don't understand the nomenclature here exactly. Why do we need this?

bool position_controller_running_;
bool velocity_controller_running_;
Comment on lines +134 to +135
Copy link
Member

Choose a reason for hiding this comment

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

Why not to use one variable and use indexes defined in the above constants (line 73 and 74)?

Suggested change
bool position_controller_running_;
bool velocity_controller_running_;
size_t controller_running_;

std::chrono::system_clock::time_point begin;
Copy link
Member

Choose a reason for hiding this comment

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

Class member:

Suggested change
std::chrono::system_clock::time_point begin;
std::chrono::system_clock::time_point begin_;

// for velocity control, store last position command
std::vector<double> joint_pos_commands_old_;
};

typedef GenericSystem GenericRobot;
Expand Down
151 changes: 149 additions & 2 deletions hardware_interface/src/fake_components/generic_system.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "fake_components/generic_system.hpp"

#include <algorithm>
#include <chrono>
#include <cmath>
#include <iterator>
#include <limits>
Expand Down Expand Up @@ -47,6 +48,18 @@ return_type GenericSystem::configure(const hardware_interface::HardwareInfo & in
fake_sensor_command_interfaces_ = false;
}

// check if there is parameter that disables commands
// this way we simulate disconnected driver
it = info_.hardware_parameters.find("disable_commands");
if (it != info.hardware_parameters.end())
{
command_propagation_disabled_ = it->second == "true" || it->second == "True";
destogl marked this conversation as resolved.
Show resolved Hide resolved
}
else
{
command_propagation_disabled_ = false;
}

// process parameters about state following
position_state_following_offset_ = 0.0;
custom_interface_with_following_offset_ = "";
Expand All @@ -66,6 +79,7 @@ return_type GenericSystem::configure(const hardware_interface::HardwareInfo & in

// Initialize storage for standard interfaces
initialize_storage_vectors(joint_commands_, joint_states_, standard_interfaces_);

Copy link
Member

Choose a reason for hiding this comment

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

Suggested change

// set all values without initial values to 0
for (auto i = 0u; i < info_.joints.size(); i++)
{
Expand All @@ -78,6 +92,16 @@ return_type GenericSystem::configure(const hardware_interface::HardwareInfo & in
}
}

// set memory position vector to initial value
joint_pos_commands_old_.resize(joint_commands_[POSITION_INTERFACE_INDEX].size());
joint_pos_commands_old_ = joint_commands_[POSITION_INTERFACE_INDEX];

// joint velocity commands to zero
for (auto i = 0u; i < joint_commands_[VELOCITY_INTERFACE_INDEX].size(); ++i)
{
joint_commands_[VELOCITY_INTERFACE_INDEX][i] = 0.0;
}

// Search for mimic joints
for (auto i = 0u; i < info_.joints.size(); ++i)
{
Expand Down Expand Up @@ -180,6 +204,15 @@ return_type GenericSystem::configure(const hardware_interface::HardwareInfo & in
}
initialize_storage_vectors(sensor_fake_commands_, sensor_states_, sensor_interfaces_);

stop_modes_ = {StoppingInterface::NONE, StoppingInterface::NONE, StoppingInterface::NONE,
StoppingInterface::NONE, StoppingInterface::NONE, StoppingInterface::NONE};
start_modes_ = {hardware_interface::HW_IF_POSITION, hardware_interface::HW_IF_POSITION,
hardware_interface::HW_IF_POSITION, hardware_interface::HW_IF_POSITION,
hardware_interface::HW_IF_POSITION, hardware_interface::HW_IF_POSITION};
position_controller_running_ = false;
velocity_controller_running_ = false;
begin = std::chrono::system_clock::now();

status_ = hardware_interface::status::CONFIGURED;
return hardware_interface::return_type::OK;
}
Expand Down Expand Up @@ -278,20 +311,134 @@ std::vector<hardware_interface::CommandInterface> GenericSystem::export_command_
return command_interfaces;
}

return_type GenericSystem::prepare_command_mode_switch(
const std::vector<std::string> & start_interfaces,
const std::vector<std::string> & stop_interfaces)
{
hardware_interface::return_type ret_val = hardware_interface::return_type::OK;

start_modes_.clear();
stop_modes_.clear();

// Starting interfaces
// add start interface per joint in tmp var for later check
for (const auto & key : start_interfaces)
{
for (auto i = 0u; i < info_.joints.size(); i++)
{
if (key == info_.joints[i].name + "/" + hardware_interface::HW_IF_POSITION)
{
start_modes_.push_back(hardware_interface::HW_IF_POSITION);
}
if (key == info_.joints[i].name + "/" + hardware_interface::HW_IF_VELOCITY)
{
start_modes_.push_back(hardware_interface::HW_IF_VELOCITY);
}
}
Comment on lines +318 to +337
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
hardware_interface::return_type ret_val = hardware_interface::return_type::OK;
start_modes_.clear();
stop_modes_.clear();
// Starting interfaces
// add start interface per joint in tmp var for later check
for (const auto & key : start_interfaces)
{
for (auto i = 0u; i < info_.joints.size(); i++)
{
if (key == info_.joints[i].name + "/" + hardware_interface::HW_IF_POSITION)
{
start_modes_.push_back(hardware_interface::HW_IF_POSITION);
}
if (key == info_.joints[i].name + "/" + hardware_interface::HW_IF_VELOCITY)
{
start_modes_.push_back(hardware_interface::HW_IF_VELOCITY);
}
}
hardware_interface::return_type ret_val = hardware_interface::return_type::OK;
// Currently we don't accept ACCELERATION-only and EFFORT-only interfaces
for (const auto & key : start_interfaces)
{
for (auto i = 0ul; i < info_.joints.size(); i++)
{
if (key == info_.joints[i].name + "/" + hardware_interface::HW_IF_ACCELERATION ||
key == info_.joints[i].name + "/" + hardware_interface::HW_IF_EFFORT)
{
ret_val = false;
}
}
return ret_val;

Copy link
Member

Choose a reason for hiding this comment

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

Also not allowed if velocity is missing and there are only ACC and POS interfaces.

}

// Stopping interfaces
// add stop interface per joint in tmp var for later check
for (const auto & key : stop_interfaces)
{
for (auto i = 0u; i < info_.joints.size(); i++)
{
if (key == info_.joints[i].name + "/" + hardware_interface::HW_IF_POSITION)
{
stop_modes_.push_back(StoppingInterface::STOP_POSITION);
}
if (key == info_.joints[i].name + "/" + hardware_interface::HW_IF_VELOCITY)
{
stop_modes_.push_back(StoppingInterface::STOP_VELOCITY);
}
}
}

return ret_val;
}

return_type GenericSystem::perform_command_mode_switch(
const std::vector<std::string> & /*start_interfaces*/,
const std::vector<std::string> & /*stop_interfaces*/)
Comment on lines +361 to +362
Copy link
Member

Choose a reason for hiding this comment

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

This probably shouldn't be commented out and then we dont' have to store interfaces for starting and stopping.

{
hardware_interface::return_type ret_val = hardware_interface::return_type::OK;

position_controller_running_ = false;
velocity_controller_running_ = false;

if (
start_modes_.size() != 0 &&
std::find(start_modes_.begin(), start_modes_.end(), hardware_interface::HW_IF_POSITION) !=
start_modes_.end())
{
for (size_t i = 0; i < joint_commands_[POSITION_INTERFACE_INDEX].size(); ++i)
{
joint_commands_[POSITION_INTERFACE_INDEX][i] = joint_states_[POSITION_INTERFACE_INDEX][i];
}
position_controller_running_ = true;
}

if (
start_modes_.size() != 0 &&
std::find(start_modes_.begin(), start_modes_.end(), hardware_interface::HW_IF_VELOCITY) !=
start_modes_.end())
{
for (size_t i = 0; i < joint_commands_[VELOCITY_INTERFACE_INDEX].size(); ++i)
{
joint_commands_[VELOCITY_INTERFACE_INDEX][i] = 0.0;
}
velocity_controller_running_ = true;
}
return ret_val;
Comment on lines +364 to +392
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
hardware_interface::return_type ret_val = hardware_interface::return_type::OK;
position_controller_running_ = false;
velocity_controller_running_ = false;
if (
start_modes_.size() != 0 &&
std::find(start_modes_.begin(), start_modes_.end(), hardware_interface::HW_IF_POSITION) !=
start_modes_.end())
{
for (size_t i = 0; i < joint_commands_[POSITION_INTERFACE_INDEX].size(); ++i)
{
joint_commands_[POSITION_INTERFACE_INDEX][i] = joint_states_[POSITION_INTERFACE_INDEX][i];
}
position_controller_running_ = true;
}
if (
start_modes_.size() != 0 &&
std::find(start_modes_.begin(), start_modes_.end(), hardware_interface::HW_IF_VELOCITY) !=
start_modes_.end())
{
for (size_t i = 0; i < joint_commands_[VELOCITY_INTERFACE_INDEX].size(); ++i)
{
joint_commands_[VELOCITY_INTERFACE_INDEX][i] = 0.0;
}
velocity_controller_running_ = true;
}
return ret_val;
hardware_interface::return_type ret_val = hardware_interface::return_type::OK;
// class variable
std::vector<std::vector<bool>> used_interface_per_joint_[interface_type][joint];
// set everything to false first
for (const auto & interface : start_interfaces)
{
joint_name = split (interface.split("/")[0])
interface_name = split (interface.split("/")[1])
auto found_it = std::find(standard_interfaces_.begin(), standard_interfaces_.end(), interface_name)
if (found_it != standard_interfaces_.end())
{
auto pos = std::dist(standard_interfaces_.begin(), found_it);
auto found_joint = std::find_if(info_.joints.being(), info_.joints.end(), [&](const auto & joint) { return joint.name == joint_name; });
auto joint_pos = std::dist(info_.joints.begin(), found_joint);
used_interface_per_joint_[dist][joint_pos] = true;
}
return true;

}

return_type GenericSystem::read()
{
std::chrono::system_clock::time_point begin_last = begin;
begin = std::chrono::system_clock::now();
double period =
std::chrono::duration_cast<std::chrono::milliseconds>(begin - begin_last).count() / 1000.0;

// apply offset to positions only
for (size_t j = 0; j < joint_states_[POSITION_INTERFACE_INDEX].size(); ++j)
{
if (!std::isnan(joint_commands_[POSITION_INTERFACE_INDEX][j]))
if (
!std::isnan(joint_commands_[POSITION_INTERFACE_INDEX][j]) && !command_propagation_disabled_ &&
position_controller_running_)
{
joint_states_[POSITION_INTERFACE_INDEX][j] =
joint_commands_[POSITION_INTERFACE_INDEX][j] +
(custom_interface_with_following_offset_.empty() ? position_state_following_offset_ : 0.0);

if (info_.joints[j].state_interfaces.size() > 1)
joint_states_[VELOCITY_INTERFACE_INDEX][j] =
(joint_commands_[POSITION_INTERFACE_INDEX][j] - joint_pos_commands_old_[j]) / period;
}
}

// velocity
for (size_t j = 0; j < joint_commands_[VELOCITY_INTERFACE_INDEX].size(); ++j)
{
if (
!std::isnan(joint_commands_[VELOCITY_INTERFACE_INDEX][j]) && !command_propagation_disabled_ &&
velocity_controller_running_)
{
if (!position_controller_running_)
{
joint_states_[POSITION_INTERFACE_INDEX][j] +=
joint_commands_[VELOCITY_INTERFACE_INDEX][j] * period;
joint_commands_[POSITION_INTERFACE_INDEX][j] = joint_states_[POSITION_INTERFACE_INDEX][j];
}

joint_states_[VELOCITY_INTERFACE_INDEX][j] = joint_commands_[VELOCITY_INTERFACE_INDEX][j];
}
}

// remember old value of position
joint_pos_commands_old_ = joint_commands_[POSITION_INTERFACE_INDEX];

// do loopback on all other interfaces - starts from 1 because 0 index is position interface
Copy link
Member

Choose a reason for hiding this comment

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

Comment needs update

for (size_t i = 1; i < joint_states_.size(); ++i)
for (size_t i = 2; i < joint_states_.size(); ++i)
{
for (size_t j = 0; j < joint_states_[i].size(); ++j)
{
Expand Down