Revision 6d13138a src/server/neck_motion_generator.cpp
src/server/neck_motion_generator.cpp | ||
---|---|---|
32 | 32 |
#include "humotion/server/server.h" |
33 | 33 |
|
34 | 34 |
using humotion::server::NeckMotionGenerator; |
35 |
|
|
36 |
const float NeckMotionGenerator::CONST_GUITTON87_A = 4.39/2.0; |
|
37 |
const float NeckMotionGenerator::CONST_GUITTON87_B = 106.0/2.0; |
|
38 |
|
|
39 |
// healthy adult human: 12-15 breaths/min (see "Ganong's review of medical physiology") |
|
40 |
// total: 60/12-15 = 3-5s |
|
41 |
// inhale 1.5-2s |
|
42 |
// exhale 1.5-2s |
|
43 |
// pause 2s |
|
44 |
const float NeckMotionGenerator::CONST_BREATH_PERIOD = 1500.0+1500.0+1500.0; // given in ms |
|
45 |
const float NeckMotionGenerator::CONST_BREATH_AMPLITUDE = 1.0; // degrees |
|
46 |
|
|
35 |
using humotion::server::Config; |
|
47 | 36 |
|
48 | 37 |
//! constructor |
49 |
NeckMotionGenerator::NeckMotionGenerator(JointInterface *j) : |
|
50 |
GazeMotionGenerator(j, 3, 1.0/Server::MOTION_UPDATERATE) { |
|
38 |
NeckMotionGenerator::NeckMotionGenerator(JointInterface *j, Config *cfg) :
|
|
39 |
GazeMotionGenerator(j, cfg, 3, 1.0/Server::MOTION_UPDATERATE) {
|
|
51 | 40 |
breath_time_ = 0.0; |
52 | 41 |
} |
53 | 42 |
|
... | ... | |
62 | 51 |
// we want to have a constant acceleration |
63 | 52 |
// -> triangular wave as speeds -> (x<0.5)? 2*x*x: 1- 2*(1-x)**2 = 4x - 2x**2 - 1 |
64 | 53 |
float breath_offset = 0.0; |
54 |
|
|
65 | 55 |
// 0...1 -> move up, 1..2 -> return, 2..3 -> still |
66 |
float breath_time_normalized = (breath_time_ * 3)/CONST_BREATH_PERIOD;
|
|
56 |
float breath_time_normalized = (breath_time_ * 3)/config->breath_period;
|
|
67 | 57 |
|
68 | 58 |
if (breath_time_normalized <= 0.5) { |
69 | 59 |
// accelerated motion |
70 |
breath_offset = CONST_BREATH_AMPLITUDE * (2.0 * pow(breath_time_normalized, 2));
|
|
60 |
breath_offset = config->breath_amplitude * (2.0 * pow(breath_time_normalized, 2));
|
|
71 | 61 |
} else if (breath_time_normalized <= 1.0) { |
72 | 62 |
// deaccelerate |
73 |
breath_offset = CONST_BREATH_AMPLITUDE * (1.0 - 2.0 * pow(1.0 - breath_time_normalized, 2)); |
|
63 |
breath_offset = config->breath_amplitude * (1.0 - 2.0 |
|
64 |
* pow(1.0 - breath_time_normalized, 2)); |
|
74 | 65 |
} else if (breath_time_normalized <= 1.5) { |
75 | 66 |
// accelerate again |
76 |
breath_offset = CONST_BREATH_AMPLITUDE * (1.0 - (2.0 * pow(breath_time_normalized-1, 2)));
|
|
67 |
breath_offset = config->breath_amplitude * (1.0 - (2.0 * pow(breath_time_normalized-1, 2)));
|
|
77 | 68 |
} else if (breath_time_normalized <= 2.0) { |
78 |
breath_offset = CONST_BREATH_AMPLITUDE * (2.0 * pow(2.0 - breath_time_normalized, 2));
|
|
69 |
breath_offset = config->breath_amplitude * (2.0 * pow(2.0 - breath_time_normalized, 2));
|
|
79 | 70 |
} else if (breath_time_normalized <= 3.0) { |
80 | 71 |
// pause for some time |
81 | 72 |
breath_offset = 0; |
... | ... | |
83 | 74 |
|
84 | 75 |
// fetch next time |
85 | 76 |
breath_time_ += 1000.0/Server::MOTION_UPDATERATE; |
86 |
if (breath_time_ >= CONST_BREATH_PERIOD) { |
|
87 |
breath_time_ -= CONST_BREATH_PERIOD; |
|
77 |
|
|
78 |
if (breath_time_ >= config->breath_period) { |
|
79 |
breath_time_ -= config->breath_period; |
|
88 | 80 |
} |
89 | 81 |
|
90 | 82 |
return breath_offset; |
... | ... | |
205 | 197 |
// get distance to target |
206 | 198 |
float distance_abs = fabs(target - current_position); |
207 | 199 |
|
208 |
// get max speed: according to [guitton87] there is a relation
|
|
200 |
// get max speed: according to the equation Hmax from [guitton87] there is a linear relation
|
|
209 | 201 |
// between distance_abs and v_max_head: |
210 | 202 |
// v_max = 4.39 * d_total + 106.0 (in degrees) |
211 |
float max_speed = (CONST_GUITTON87_A * distance_abs + CONST_GUITTON87_B); |
|
203 |
float max_velocity = 4.39 * distance_abs + 106.0; |
|
204 |
|
|
205 |
// scale and limit max speed: |
|
206 |
max_velocity = max_velocity * config->scale_velocity_neck; |
|
207 |
max_velocity = fmin(max_velocity, config->limit_velocity_neck); |
|
212 | 208 |
|
213 | 209 |
// max accel: assuming linear acceleration we have: |
214 | 210 |
/* v ^ _ |
... | ... | |
225 | 221 |
// and therefore |
226 | 222 |
// a = v_max^2 / d_total |
227 | 223 |
float max_accel = 0.0; |
224 |
|
|
228 | 225 |
if (distance_abs > 0.0) { |
229 |
max_accel = pow(max_speed, 2) / distance_abs;
|
|
226 |
max_accel = pow(max_velocity, 2) / distance_abs;
|
|
230 | 227 |
} |
231 | 228 |
|
232 |
// smoother motion |
|
233 |
max_accel = max_accel * 0.7; |
|
229 |
// scale and limit acceleration |
|
230 |
max_accel = max_accel * config->scale_acceleration_neck; |
|
231 |
max_accel = fmin(max_accel, config->limit_acceleration_neck); |
|
234 | 232 |
|
235 |
// limit maximum acceleration to reduce noise FIXME! |
|
236 |
if (max_accel > 1000) { |
|
237 |
max_accel = 1000; |
|
238 |
} |
|
239 | 233 |
// printf("MAX SPEED %4.2f / max accel %4.2f\n",max_speed, max_accel); |
240 | 234 |
|
241 | 235 |
// feed reflexxes api with data |
242 | 236 |
reflexxes_set_input(dof, target, current_position, current_velocity, |
243 |
timestamp, max_speed, max_accel);
|
|
237 |
timestamp, max_velocity, max_accel);
|
|
244 | 238 |
} |
Also available in: Unified diff