00001
00002
00003
00004
00005
00006
00007
00008
00017 #include <errno.h>
00018 #include <stdio.h>
00019
00020 #include <art/conversions.h>
00021 #include "model_brake.h"
00022
00023 namespace
00024 {
00025 static double EPSILON_SECONDS = 0.000001;
00026 static double EPSILON_TICKS = 0.5;
00027 }
00028
00030 ArtBrakeModel::ArtBrakeModel(float init_pos)
00031 {
00032 am_ = new Animatics;
00033
00034
00035 ros::NodeHandle mynh("~");
00036
00037
00038 double accel_limit_in, max_vel_in;
00039 mynh.param("actuator_accel", accel_limit_in, 8.0);
00040 ROS_INFO("model actuator acceleration as %.2f in/s^2", accel_limit_in);
00041 mynh.param("actuator_max_vel", max_vel_in, 4.0);
00042 ROS_INFO("model max actuator velocity as %.2f in/s", max_vel_in);
00043
00044
00045 double ticks_per_inch = 24000;
00046 actuator_accel_ = rint(accel_limit_in * ticks_per_inch);
00047 actuator_max_vel_ = rint(max_vel_in * ticks_per_inch);
00048
00049
00050 sim_status_ = 0;
00051 brake_position_ = init_pos;
00052 sim_encoder_ = encoder_goal_ = am_->pos2enc(brake_position_);
00053 x_ = (double) sim_encoder_;
00054 a_ = 0;
00055 v_ = 0;
00056 update_sensors(brake_position_);
00057 last_update_time_ = ros::Time::now().toSec();
00058 }
00059
00060 ArtBrakeModel::~ArtBrakeModel()
00061 {
00062 delete am_;
00063 }
00064
00070 int ArtBrakeModel::interpret(const char *string, char *status, int nbytes)
00071 {
00072
00073 if (nbytes > 0)
00074 status[0] = '\0';
00075
00076
00077 if (string == NULL)
00078 return EIO;
00079
00080
00081 update();
00082
00083 int retval = 0;
00084
00085
00086 switch (string[0])
00087 {
00088 case 'c':
00089 if (0 == strcmp(string, "c=UEA Rc\n"))
00090 {
00091
00092 snprintf(status, nbytes, "%d\n", digital_potentiometer_);
00093 }
00094 else if (0 == strcmp(string, "c=UAA Rc\n"))
00095 {
00096
00097 snprintf(status, nbytes, "%d\n", digital_pressure_);
00098 }
00099 break;
00100
00101 case 'D':
00102
00103 int encoder_delta;
00104 if (1 == sscanf(string, "D=%d RW G\n", &encoder_delta))
00105 {
00106
00107 encoder_goal_ = am_->clamp_encoder(sim_encoder_ + encoder_delta);
00108
00109
00110 plan(encoder_delta);
00111
00112 ROS_DEBUG("simulated encoder delta: %d, goal: %d",
00113 encoder_delta, encoder_goal_);
00114 sim_status_ |= Status_Bt;
00115 snprintf(status, nbytes, "%d\n", sim_status_);
00116 }
00117 else
00118 retval = EIO;
00119 break;
00120
00121 case 'R':
00122 if (0 == strcmp(string, "RP\n"))
00123 {
00124
00125 snprintf(status, nbytes, "%d\n", sim_encoder_);
00126 }
00127 break;
00128
00129 case 'Z':
00130 if (0 == strcmp(string, "ZS RW\n"))
00131 {
00132
00133 sim_status_ = 0;
00134 snprintf(status, nbytes, "%d\n", sim_status_);
00135 }
00136 break;
00137
00138 default:
00139
00140 ;
00141 }
00142
00143 return retval;
00144 }
00145
00154 void ArtBrakeModel::move(double start, double finish)
00155 {
00156 double t = start;
00157 while (t < finish)
00158 {
00159 a_ = plan_.next(t);
00160 double dt = plan_.interval(t, finish);
00161 double v0 = v_;
00162 v_ += dt * a_;
00163 x_ += dt * (v_ + v0)/2.0;
00164 t += dt;
00165 #if 0
00166
00167
00168 if ((x_ < am_->encoder_min_ - EPSILON_TICKS)
00169 || (x_ > am_->encoder_max_ + EPSILON_TICKS))
00170 ROS_WARN("actuator out of range: (time %.6f): %.f, %.f, %.f",
00171 t, x_, v_, a_);
00172 #endif
00173
00174
00175 if (x_ < am_->encoder_min_ - EPSILON_TICKS)
00176 x_ = am_->encoder_min_;
00177 else if (x_ > am_->encoder_max_ + EPSILON_TICKS)
00178 x_ = am_->encoder_max_;
00179 ROS_DEBUG("actuator (time %.6f): %.f, %.f, %.f (%.6f)",
00180 t, x_, v_, a_, dt);
00181 }
00182
00183 if (fabs(finish-t) >= EPSILON_SECONDS)
00184 ROS_WARN("ArtBrakeModel::move() finished early (%.6f < %.6f)", t, finish);
00185 }
00186
00206 double ArtBrakeModel::plan(double dx)
00207 {
00208 double t0 = ros::Time::now().toSec();
00209 double a;
00210
00211 if (fabs(dx) > EPSILON_TICKS)
00212 a = getAccel(dx);
00213 else if (fabs(v_) > EPSILON_TICKS)
00214 a = getAccel(-v_);
00215 else
00216 {
00217 plan_.reset();
00218 return 0.0;
00219 }
00220
00221 double dt_h = -v_/a;
00222 double dx_h = dx - 0.5 * v_ * dt_h;
00223 double dt2 = sqrt(dx_h/a);
00224 double dt1 = dt2 + dt_h;
00225 double dt = dt1 + dt2;
00226
00227
00228 plan_.reset();
00229 if (dt1 > EPSILON_SECONDS)
00230 plan_.append(t0 + dt1, a);
00231 if (dt2 > EPSILON_SECONDS)
00232 plan_.append(t0 + dt, -a);
00233
00234
00235 plan_.log();
00236 ROS_DEBUG("plan(%.f) time %.6f, dt: %.6f, dt1: %.6f, dt2: %.6f",
00237 dx, t0, dt, dt1, dt2);
00238
00239 return dt;
00240 }
00241
00243 void ArtBrakeModel::update(void)
00244 {
00245 double now = ros::Time::now().toSec();
00246
00247
00248 #if 1
00249 move(last_update_time_, now);
00250 sim_encoder_ = rint(x_);
00251 #else
00252 sim_encoder_ = encoder_goal_;
00253 #endif
00254 if (plan_.finished())
00255 sim_status_ &= (~Status_Bt);
00256
00257
00258 brake_position_ = limit_travel(am_->enc2pos(sim_encoder_));
00259
00260 if (sim_encoder_ <= am_->encoder_min_)
00261 {
00262 sim_status_ |= (Status_Bm | Status_Bl);
00263 ROS_DEBUG("-limit reached, status: 0x%.02x", sim_status_);
00264 }
00265 else
00266 sim_status_ &= (~Status_Bm);
00267
00268 if (sim_encoder_ >= am_->encoder_max_)
00269 {
00270 sim_status_ |= (Status_Bp | Status_Br);
00271 ROS_DEBUG("+limit reached, status: 0x%.02x", sim_status_);
00272 }
00273 else
00274 sim_status_ &= (~Status_Bp);
00275
00276 update_sensors(brake_position_);
00277
00278 ROS_DEBUG("Brake model: 0x%02x [%.3f, %d, %d, %d] %.6f",
00279 sim_status_, brake_position_, digital_potentiometer_,
00280 digital_pressure_, sim_encoder_, now);
00281
00282 last_update_time_ = now;
00283 }
00284
00285 void ArtBrakeModel::update_sensors(float position)
00286 {
00287 digital_pressure_ =
00288 analog_to_digital(am_->pos2press(position), 5.0, 10);
00289 digital_potentiometer_ =
00290 analog_to_digital(am_->pos2pot(position), 5.0, 10);
00291 }