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