@@ -73,11 +73,15 @@ RCSotController::RCSotController()
73
73
: // Store 32 DoFs for 5 minutes (1 Khz: 5*60*1000)
74
74
// -> 124 Mo of data.
75
75
type_name_ (" RCSotController" ), simulation_mode_(false ),
76
- accumulated_time_ (0.0 ), jitter_(0.0 ), verbosity_level_(0 ) {
76
+ subSampling_ (0 ), step_(0 ), verbosity_level_(0 ), io_service_(),
77
+ io_work_ (io_service_), sotComputing_(false )
78
+ {
77
79
RESETDEBUG4 ();
78
80
}
79
81
80
82
RCSotController::~RCSotController () {
83
+ io_service_.stop ();
84
+ thread_pool_.join_all ();
81
85
std::string afilename (" /tmp/sot.log" );
82
86
83
87
RcSotLog_.record (DataOneIter_);
@@ -620,13 +624,6 @@ bool RCSotController::readParamsControlMode(ros::NodeHandle &robot_nh) {
620
624
}
621
625
622
626
bool RCSotController::readParamsdt (ros::NodeHandle &robot_nh) {
623
- // / Reading the jitter is optional but it is a very good idea.
624
- if (robot_nh.hasParam (" /sot_controller/jitter" )) {
625
- robot_nh.getParam (" /sot_controller/jitter" , jitter_);
626
- if (verbosity_level_ > 0 )
627
- ROS_INFO_STREAM (" jitter: " << jitter_);
628
- }
629
-
630
627
// / Read /sot_controller/dt to know what is the control period
631
628
if (robot_nh.hasParam (" /sot_controller/dt" )) {
632
629
robot_nh.getParam (" /sot_controller/dt" , dt_);
@@ -952,13 +949,19 @@ void RCSotController::readControl(
952
949
DataOneIter_.controls [i] = command_[i];
953
950
}
954
951
955
- } else
952
+ } else {
956
953
ROS_INFO_STREAM (" no control." );
954
+ localStandbyEffortControlMode (ros::Duration (dtRos_));
955
+ localStandbyVelocityControlMode (ros::Duration (dtRos_));
956
+ localStandbyPositionControlMode ();
957
+ }
957
958
}
958
959
959
960
void RCSotController::one_iteration () {
961
+ sotComputing_ = true ;
960
962
// Chrono start
961
963
RcSotLog_.start_it ();
964
+
962
965
// / Update the sensors.
963
966
fillSensors ();
964
967
@@ -973,21 +976,24 @@ void RCSotController::one_iteration() {
973
976
974
977
throw e;
975
978
}
976
-
977
979
try {
978
- sotController_->getControl (controlValues_ );
980
+ sotController_->getControl (controlValues_copy_ );
979
981
} catch (std::exception &e) {
980
982
std::cerr << " Failure happened during one_iteration(): "
981
983
<< " when calling getControl " << std::endl;
982
984
std::cerr << __FILE__ << " " << __LINE__ << std::endl
983
- << e.what () << std::endl;;
985
+ << e.what () << std::endl;
984
986
throw e;
985
987
}
986
988
987
-
988
- // / Read the control values
989
- readControl (controlValues_);
990
-
989
+ // Wait until last subsampling step to write result in controlValues_
990
+ while (step_ != subSampling_ - 1 ){
991
+ ros::Duration (.01 *dtRos_).sleep ();
992
+ }
993
+ // mutex
994
+ mutex_.lock ();
995
+ controlValues_ = controlValues_copy_;
996
+ mutex_.unlock ();
991
997
// Chrono stop.
992
998
double it_duration = RcSotLog_.stop_it ();
993
999
if (it_duration > dt_) {
@@ -997,6 +1003,7 @@ void RCSotController::one_iteration() {
997
1003
998
1004
// / Store everything in Log.
999
1005
RcSotLog_.record (DataOneIter_);
1006
+ sotComputing_ = false ;
1000
1007
}
1001
1008
1002
1009
void RCSotController::localStandbyEffortControlMode (
@@ -1085,16 +1092,81 @@ void RCSotController::localStandbyPositionControlMode() {
1085
1092
first_time = false ;
1086
1093
}
1087
1094
1095
+ void RCSotController::computeSubSampling (const ros::Duration &period)
1096
+ {
1097
+ if (subSampling_ != 0 ) return ; // already computed
1098
+ dtRos_ = period.toSec ();
1099
+ double ratio = dt_/dtRos_;
1100
+ if (fabs (ratio - std::round (ratio)) > 1e-8 ){
1101
+ std::ostringstream os;
1102
+ os << " SoT period (" << dt_ << " ) is not a multiple of roscontrol period ("
1103
+ << dtRos_ << " ). Modify rosparam /sot_controller/dt to a "
1104
+ " multiple of roscontrol period." ;
1105
+ throw std::runtime_error (os.str ().c_str ());
1106
+ }
1107
+ subSampling_ = static_cast <std::size_t >(std::round (ratio));
1108
+ // First time method update is called, step_ will turn to 1.
1109
+ step_ = subSampling_ -1 ;
1110
+ ROS_INFO_STREAM (" Subsampling SoT graph computation by ratio "
1111
+ << subSampling_);
1112
+ if (subSampling_ != 1 ){
1113
+ // create thread in this method instead of in constructor to inherit the
1114
+ // same priority level.
1115
+ // If subsampling is equal to one, the control graph is evaluated in the
1116
+ // same thread.
1117
+ thread_pool_.create_thread (boost::bind (&boost::asio::io_service::run,
1118
+ &io_service_));
1119
+ }
1120
+
1121
+ }
1088
1122
void RCSotController::update (const ros::Time &, const ros::Duration &period) {
1089
1123
// Do not send any control if the dynamic graph is not started
1090
1124
if (!isDynamicGraphStopped ()) {
1125
+ // Increment step at beginning of this method since the end time may
1126
+ // vary a lot.
1127
+ ++ step_;
1128
+ if (step_ == subSampling_) step_ = 0 ;
1091
1129
try {
1092
- double periodInSec = period.toSec ();
1093
- if (periodInSec + accumulated_time_ > dt_ - jitter_) {
1094
- one_iteration ();
1095
- accumulated_time_ = 0.0 ;
1096
- } else
1097
- accumulated_time_ += periodInSec;
1130
+ // If subsampling is equal to 1, i.e. no subsampling, evaluate
1131
+ // control graph in this thread
1132
+ if (subSampling_ == 1 ){
1133
+ one_iteration ();
1134
+ } else {
1135
+ if (step_ == 0 ){
1136
+ // If previous graph evaluation is not finished, do not start a new
1137
+ // one.
1138
+ if (!sotComputing_){
1139
+ io_service_.post (boost::bind (&RCSotController::one_iteration,this ));
1140
+ } else {
1141
+ ROS_INFO_STREAM (" Sot computation not finished yet." );
1142
+ }
1143
+ // protected read control
1144
+ mutex_.lock ();
1145
+ // / Read the control values
1146
+ readControl (controlValues_);
1147
+ mutex_.unlock ();
1148
+ } else {
1149
+ // protected read control
1150
+ mutex_.lock ();
1151
+ // If the robot is controlled in position, update the reference
1152
+ // posture with the latest velocity.
1153
+ // Note that the entry "velocity" only exists if the robot is
1154
+ // controlled in position.
1155
+ if (controlValues_.find (" velocity" ) != controlValues_.end ()){
1156
+ std::vector<double > control = controlValues_[" control" ].getValues ();
1157
+ const std::vector<double >& velocity = controlValues_[" velocity" ].
1158
+ getValues ();
1159
+ for (std::size_t i=0 ; i<control.size (); ++i){
1160
+ control[i] += dtRos_ * velocity[i];
1161
+ }
1162
+ controlValues_[" control" ].setValues (control);
1163
+ }
1164
+ // / Read the control values
1165
+ readControl (controlValues_);
1166
+ mutex_.unlock ();
1167
+ }
1168
+ }
1169
+
1098
1170
} catch (std::exception const &exc) {
1099
1171
ROS_ERROR_STREAM (" Failure happened during one_iteration evaluation: "
1100
1172
<< exc.what () << " \n Use gdb to investiguate the problem\n "
@@ -1107,6 +1179,7 @@ void RCSotController::update(const ros::Time &, const ros::Duration &period) {
1107
1179
throw ;
1108
1180
}
1109
1181
} else {
1182
+ computeSubSampling (period);
1110
1183
// / Update the sensors.
1111
1184
fillSensors ();
1112
1185
try {
0 commit comments