Skip to content
This repository was archived by the owner on Dec 1, 2020. It is now read-only.

Commit 2ea1a36

Browse files
Merge pull request #278 from project-march/feature/PM-458-implement-inertia-calculations-in-a-controller
Feature/PM-458: implement inertia calculations in a controller
2 parents 7ace5ca + 373bfdf commit 2ea1a36

File tree

10 files changed

+935
-37
lines changed

10 files changed

+935
-37
lines changed

march_joint_inertia_controller/CMakeLists.txt

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,23 +4,42 @@ project(march_joint_inertia_controller)
44
add_compile_options(-std=c++14 -Wall -Wextra -Werror)
55

66
find_package(catkin REQUIRED COMPONENTS
7+
actionlib
8+
actionlib_msgs
9+
control_msgs
710
controller_interface
11+
controller_manager
12+
joint_state_controller
13+
joint_trajectory_controller
14+
march_hardware
15+
march_shared_resources
816
pluginlib
17+
realtime_tools
918
roscpp
19+
std_msgs
20+
urdf
1021
)
1122

1223
catkin_package(
1324
INCLUDE_DIRS include
1425
LIBRARIES ${PROJECT_NAME}
1526
CATKIN_DEPENDS
27+
actionlib_msgs
28+
control_msgs
1629
controller_interface
1730
pluginlib
1831
roscpp
32+
std_msgs
1933
)
2034

2135
include_directories(include SYSTEM ${catkin_INCLUDE_DIRS})
2236

23-
add_library(${PROJECT_NAME} src/joint_inertia_controller.cpp)
37+
add_library(${PROJECT_NAME}
38+
include/${PROJECT_NAME}/inertia_estimator.h
39+
include/${PROJECT_NAME}/joint_trajectory_inertia_controller.h
40+
src/inertia_estimator.cpp
41+
src/joint_inertia_controller.cpp
42+
src/joint_trajectory_inertia_controller.cpp)
2443
target_link_libraries(${PROJECT_NAME} ${catkin_LIBRARIES})
2544

2645
install(DIRECTORY include/${PROJECT_NAME}/
Lines changed: 93 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,94 @@
1+
# This is a template for the controllers.yaml used in the HWI and in the simulation, note the inertia_estimator.
2+
13
march:
2-
joint_inertia_controller:
3-
type: joint_inertia_controller/InertiaController
4-
joints:
5-
- left_ankle
6-
- left_hip_aa
7-
- left_hip_fe
8-
- left_knee
9-
- right_ankle
10-
- right_hip_aa
11-
- right_hip_fe
12-
- right_knee
4+
controller:
5+
pdb_state:
6+
type: march_pdb_state_controller/MarchPdbStateController
7+
publish_rate: 50
8+
joint_state:
9+
type: joint_state_controller/JointStateController
10+
publish_rate: 250
11+
temperature_sensor:
12+
type: march_temperature_sensor_controller/MarchTemperatureSensorController
13+
publish_rate: 1
14+
joint_inertia_controller:
15+
type: joint_inertia_controller/InertiaController
16+
allow_partial_joints_goal: true
17+
joints:
18+
- left_ankle
19+
- left_hip_aa
20+
- left_hip_fe
21+
- left_knee
22+
- right_ankle
23+
- right_hip_aa
24+
- right_hip_fe
25+
- right_knee
26+
gains: # Required because we're controlling an effort interface
27+
left_ankle: {p: 0, i: 0, d: 0, i_clamp: 100, publish_state: true, antiwindup: true}
28+
left_hip_aa: {p: 0, i: 0, d: 0, i_clamp: 100, publish_state: true, antiwindup: true}
29+
left_hip_fe: {p: 0, i: 0, d: 0, i_clamp: 100, publish_state: true, antiwindup: true}
30+
left_knee: {p: 0, i: 0, d: 0, i_clamp: 100, publish_state: true, antiwindup: true}
31+
right_ankle: {p: 0, i: 0, d: 0, i_clamp: 100, publish_state: true, antiwindup: true}
32+
right_hip_aa: {p: 0, i: 0, d: 0, i_clamp: 100, publish_state: true, antiwindup: true}
33+
right_hip_fe: {p: 0, i: 0, d: 0, i_clamp: 100, publish_state: true, antiwindup: true}
34+
right_knee: {p: 0, i: 0, d: 0, i_clamp: 100, publish_state: true, antiwindup: true}
35+
inertia_estimator:
36+
rotary:
37+
std_samples: 100 # number of samples used to calculate the standard deviation
38+
lambda: 0.96 # Usually chosen between 0.9 and 1.0, but not bigger than one or less than zero
39+
alpha_filter_size: 12 # Determines the filter size in the alpha calculation, recommended between 8 and 32
40+
vibration_boundaries:
41+
- 1.4
42+
- 1.9
43+
control_points:
44+
inertia:
45+
- 0.0
46+
- 1.0
47+
p:
48+
- 150
49+
- 300
50+
d:
51+
- 0
52+
- 5
53+
linear:
54+
std_samples: 100 # number of samples used to calculate the standard deviation
55+
lambda: 0.96
56+
alpha_filter_size: 12
57+
vibration_boundaries:
58+
- 1.4
59+
- 1.9
60+
control_points:
61+
inertia:
62+
- 0.0
63+
- 1.0
64+
p:
65+
- 150
66+
- 300
67+
d:
68+
- 0
69+
- 5
70+
constraints:
71+
left_ankle:
72+
trajectory: 0.305
73+
goal: 0.305
74+
left_hip_aa:
75+
trajectory: 0.305
76+
goal: 0.305
77+
left_hip_fe:
78+
trajectory: 0.305
79+
goal: 0.305
80+
left_knee:
81+
trajectory: 0.305
82+
goal: 0.305
83+
right_ankle:
84+
trajectory: 0.305
85+
goal: 0.305
86+
right_hip_aa:
87+
trajectory: 0.305
88+
goal: 0.305
89+
right_hip_fe:
90+
trajectory: 0.305
91+
goal: 0.305
92+
right_knee:
93+
trajectory: 0.305
94+
goal: 0.305
Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
1-
<library path="lib/libjoint_inertia_controller_lib">
2-
<class name="joint_inertia_controller/InertiaController"
3-
type="joint_inertia_controller::InertiaController"
4-
base_class_type="controller_interface::ControllerBase" />
1+
<library path="lib/libmarch_joint_inertia_controller">
2+
<class name="joint_inertia_controller/InertiaController"
3+
type="joint_inertia_controller::InertiaController"
4+
base_class_type="controller_interface::ControllerBase"/>
5+
<class name="inertia_trajectory_controller/JointTrajectoryController"
6+
type="inertia_trajectory_controller::JointTrajectoryController"
7+
base_class_type="controller_interface::ControllerBase"/>
58
</library>
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
// Copyright 2020 Project March.
2+
3+
#ifndef MARCH_WS_INERTIA_ESTIMATOR_H
4+
#define MARCH_WS_INERTIA_ESTIMATOR_H
5+
6+
#include <hardware_interface/joint_command_interface.h>
7+
#include <list>
8+
#include <ros/ros.h>
9+
#include <trajectory_interface/quintic_spline_segment.h>
10+
#include <urdf/model.h>
11+
12+
/**
13+
* \brief determines the absolute value of vector a and stores it into b so that a remains unchanged
14+
*
15+
* @param[in] a input vector with values that need to be converted to absolutes
16+
* @param[out] b output vector with copies of the absolute values of a.
17+
*/
18+
std::list<double> absolute(const std::list<double>& a);
19+
20+
/**
21+
* \brief determiness the mean value of the given vector
22+
*
23+
* @param[in] a input vector from which the mean gets calculated
24+
* @returns the mean value of a
25+
*/
26+
double mean(const std::list<double>& a);
27+
28+
/**
29+
* \brief Class that bundles functionality to estimate inertia on a Revolute Joint.
30+
*
31+
* @param[in] joint the jointhandle used for obtaining current speed and effort.
32+
* @param[in] lambda sets the lambda used in the RLS filter defaulted to 0.96
33+
* @param[in] acc_size the size of the vector wherein the calculated acceleration is stored. This vector length is also
34+
* used in determining the length of the velocity vector and the filtered acceleration vector. It is of specific
35+
* size to calculate the alpha value. Defaulted to 12.
36+
*/
37+
class InertiaEstimator
38+
{
39+
public:
40+
/**
41+
* \brief Default constructor
42+
*/
43+
InertiaEstimator(double lambda = 0.96, size_t acc_size = 12);
44+
45+
double getAcceleration();
46+
double getJointInertia();
47+
48+
void setLambda(double lambda);
49+
void setAccSize(size_t acc_size);
50+
void setVibrationBoundaries(std::vector<double> boundaries);
51+
52+
/**
53+
* \brief Applies the Butterworth filter over the last two samples and returns the resulting filtered value
54+
*/
55+
void applyButter();
56+
57+
/**
58+
* \brief Estimate the inertia using the acceleration and torque
59+
*/
60+
void inertiaEstimate();
61+
/**
62+
* \brief Calculate a discrete derivative of the speed measurements
63+
*/
64+
double discreteSpeedDerivative(const ros::Duration& period);
65+
/**
66+
* \brief Calculate the alpha coefficient for the inertia estimate
67+
*/
68+
double alphaCalculation();
69+
/**
70+
* \brief Calculate the inertia gain for the inertia estimate
71+
*/
72+
double gainCalculation();
73+
/**
74+
* \brief Calculate the correlation coefficient of the acceleration buffer
75+
*/
76+
void correlationCalculation();
77+
/**
78+
* \brief Calculate the vibration based on the acceleration
79+
*/
80+
double vibrationCalculation();
81+
82+
/**
83+
* \brief Fill the rolling buffers with corresponding values.
84+
*/
85+
void fillBuffers(double velocity, double effort, const ros::Duration& period);
86+
87+
/**
88+
* \brief Calculate the initial correlation coefficient
89+
*/
90+
void initP(unsigned int samples);
91+
92+
// Vector to be filled with samples of acceleration to determine the standard deviation from
93+
std::list<double> standard_deviation;
94+
95+
private:
96+
double min_alpha_; // You might want to be able to adjust this value from a yaml/launch file
97+
double max_alpha_; // You might want to be able to adjust this value from a yaml/launch file
98+
99+
// This is a sixth order butterworth filter with a cutoff frequency at 15Hz in Second Order Sections form
100+
std::vector<std::vector<double>> sos_{
101+
{ 9.16782507e-09, 1.83356501e-08, 9.16782507e-09, 1.00000000e+00, -1.82520938e+00, 8.33345838e-01 },
102+
{ 1.00000000e+00, 2.00000000e+00, 1.00000000e+00, 1.00000000e+00, -1.86689228e+00, 8.75214548e-01 },
103+
{ 1.00000000e+00, 2.00000000e+00, 1.00000000e+00, 1.00000000e+00, -1.94377925e+00, 9.52444269e-01 }
104+
};
105+
106+
// z1 and z2 vectors are containers for previous time-step values in the butterworth filter
107+
// Might be neater to design a separate class for the filter application for arbitrary filter sizes, datasets and
108+
// number of signals such as: https://github.com/scipy/scipy/blob/v1.5.2/scipy/signal/_sosfilt.pyx
109+
std::vector<double> z1a;
110+
std::vector<double> z2a;
111+
112+
std::vector<double> z1t;
113+
std::vector<double> z2t;
114+
115+
// Default length 12 for the alpha calculation
116+
size_t acc_size_ = 12;
117+
std::list<double> acceleration_array_;
118+
// Equal to two, because two values are needed to calculate the derivative
119+
size_t vel_size_ = acc_size_;
120+
std::list<double> velocity_array_;
121+
std::list<double> filtered_acceleration_array_;
122+
// Of length 3 for the butterworth filter
123+
size_t torque_size_ = 3;
124+
std::list<double> joint_torque_;
125+
// Of length 2 for the error calculation
126+
size_t fil_tor_size_ = 2;
127+
std::list<double> filtered_joint_torque_;
128+
129+
// Correlation coefficient used to calculate the inertia gain
130+
double corr_coeff_;
131+
double vibration_;
132+
double K_a_;
133+
double K_i_;
134+
double mean_of_absolute_;
135+
double absolute_of_mean_;
136+
double joint_inertia_;
137+
double lambda_;
138+
};
139+
140+
#endif // MARCH_WS_INERTIA_ESTIMATOR_H

march_joint_inertia_controller/include/march_joint_inertia_controller/joint_inertia_controller.h

Lines changed: 61 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,76 @@
33
#ifndef MARCH_HARDWARE_JOINT_INERTIA_CONTROLLER_H
44
#define MARCH_HARDWARE_JOINT_INERTIA_CONTROLLER_H
55

6+
#include <control_toolbox/pid.h>
67
#include <controller_interface/controller.h>
7-
#include <hardware_interface/joint_command_interface.h>
8-
#include <pluginlib/class_list_macros.h>
8+
#include "march_joint_inertia_controller/inertia_estimator.h"
9+
#include <std_msgs/Float64.h>
910

1011
namespace joint_inertia_controller
1112
{
12-
class InertiaController : public controller_interface::Controller<hardware_interface::PositionJointInterface>
13+
class InertiaController : public controller_interface::Controller<hardware_interface::EffortJointInterface>
1314
{
1415
public:
15-
bool init(hardware_interface::PositionJointInterface* hw, ros::NodeHandle& n);
16-
void update(const ros::Time& time, const ros::Duration& period);
17-
void starting(const ros::Time& time);
18-
void stopping(const ros::Time& time);
16+
struct Commands
17+
{
18+
double position; // Last commanded position
19+
double velocity; // Last commanded velocity
20+
bool has_velocity; // false if no velocity command has been specified
21+
};
22+
23+
InertiaController() = default;
24+
~InertiaController() override;
25+
26+
bool init(hardware_interface::EffortJointInterface* hw, ros::NodeHandle& n) override;
27+
void update(const ros::Time& time, const ros::Duration& period) override;
28+
void starting(const ros::Time& time) override;
29+
void stopping(const ros::Time& time) override;
30+
void setCommand(double pos_command);
31+
void setCommand(double pos_command, double vel_command);
32+
void commandCB(const std_msgs::Float64ConstPtr& msg);
33+
34+
/**
35+
* \brief Get the PID parameters
36+
*/
37+
void getGains(double& p, double& i, double& d, double& i_max, double& i_min);
38+
/**
39+
* \brief Get the PID parameters
40+
*/
41+
void getGains(double& p, double& i, double& d, double& i_max, double& i_min, bool& antiwindup);
42+
43+
/**
44+
* \brief Print debug info to console
45+
*/
46+
void printDebug();
47+
48+
/**
49+
* \brief Set the PID parameters
50+
*/
51+
void setGains(const double& p, const double& i, const double& d, const double& i_max, const double& i_min,
52+
const bool& antiwindup = false);
53+
54+
/**
55+
* \brief Return the current position of the corresponding joint
56+
*/
57+
double getPosition();
58+
59+
/**
60+
* \brief Return the name of the corresponding joint is string format
61+
*/
62+
std::string getJointName();
1963

2064
private:
65+
control_toolbox::Pid pid_controller_; /**< Internal PID controller. */
66+
67+
ros::Subscriber sub_command_;
2168
hardware_interface::JointHandle joint_;
22-
double init_pos_;
69+
70+
urdf::JointConstSharedPtr joint_urdf_;
71+
std::string joint_name_;
72+
realtime_tools::RealtimeBuffer<Commands> command_;
73+
Commands command_struct_; // pre-allocated memory that is re-used to set the realtime buffer
74+
75+
InertiaEstimator inertia_estimator_;
2376
};
2477
} // namespace joint_inertia_controller
2578

0 commit comments

Comments
 (0)