Statistics
| Branch: | Tag: | Revision:

humotion / src / server / controller.cpp @ 2aa96942

History | View | Annotate | Download (9.365 KB)

1 8c6c1163 Simon Schulz
/*
2
* This file is part of humotion
3
*
4
* Copyright(c) sschulz <AT> techfak.uni-bielefeld.de
5
* http://opensource.cit-ec.de/projects/humotion
6
*
7
* This file may be licensed under the terms of the
8
* GNU Lesser General Public License Version 3 (the ``LGPL''),
9
* or (at your option) any later version.
10
*
11
* Software distributed under the License is distributed
12
* on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
13
* express or implied. See the LGPL for the specific language
14
* governing rights and limitations.
15
*
16
* You should have received a copy of the LGPL along with this
17
* program. If not, go to http://www.gnu.org/licenses/lgpl.html
18
* or write to the Free Software Foundation, Inc.,
19
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20
*
21
* The development of this software was supported by the
22
* Excellence Cluster EXC 277 Cognitive Interaction Technology.
23
* The Excellence Cluster EXC 277 is a grant of the Deutsche
24
* Forschungsgemeinschaft (DFG) in the context of the German
25
* Excellence Initiative.
26
*/
27
28 0c8d22a5 sschulz
#include "humotion/server/controller.h"
29
#include "humotion/server/eye_motion_generator.h"
30
#include "humotion/server/eyebrow_motion_generator.h"
31
#include "humotion/server/eyelid_motion_generator.h"
32
#include "humotion/server/mouth_motion_generator.h"
33
#include "humotion/server/neck_motion_generator.h"
34
#include "humotion/timestamp.h"
35
36
// using namespace std;
37
// using namespace humotion;
38
// using namespace humotion::server;
39
40
using humotion::server::Controller;
41 6d13138a sschulz
using humotion::server::Config;
42 2aa96942 sschulz
using humotion::server::debug_data_t;
43 8c6c1163 Simon Schulz
44
//! constructor
45 ea068cf1 sschulz
Controller::Controller(JointInterface *j) {
46
    activated_ = false;
47
    joint_interface_ = j;
48 6d13138a sschulz
49
    config_ = new Config();
50 8c6c1163 Simon Schulz
}
51
52
//! destructor
53 0c8d22a5 sschulz
Controller::~Controller() {
54 8c6c1163 Simon Schulz
}
55
56
//! initialise motion generators
57 0c8d22a5 sschulz
void Controller::init_motion_generators() {
58
    // NOTE: the order of these generators is important!
59 8c6c1163 Simon Schulz
    //       (i.e. the neck generator must be added after the eye generator!)
60
61 0c8d22a5 sschulz
    // eye motion generation:
62 6d13138a sschulz
    add_motion_generator(new EyeMotionGenerator(joint_interface_, config_));
63 8c6c1163 Simon Schulz
64 0c8d22a5 sschulz
    // eyelid motion generator
65 6d13138a sschulz
    add_motion_generator(new EyelidMotionGenerator(joint_interface_, config_));
66 8c6c1163 Simon Schulz
67 0c8d22a5 sschulz
    // neck motion generator
68 6d13138a sschulz
    add_motion_generator(new NeckMotionGenerator(joint_interface_, config_));
69 8c6c1163 Simon Schulz
70 0c8d22a5 sschulz
    // mouth motion generator
71 6d13138a sschulz
    add_motion_generator(new MouthMotionGenerator(joint_interface_, config_));
72 8c6c1163 Simon Schulz
73 0c8d22a5 sschulz
    // eyebrow motion generator
74 6d13138a sschulz
    add_motion_generator(new EyebrowMotionGenerator(joint_interface_, config_));
75 8c6c1163 Simon Schulz
}
76
77
//! add a single motion genrator
78 0c8d22a5 sschulz
void Controller::add_motion_generator(MotionGenerator *m) {
79 ea068cf1 sschulz
    motion_generator_vector_.push_back(m);
80 8c6c1163 Simon Schulz
}
81
82
//! calculate target angles for all motion generators:
83 0c8d22a5 sschulz
void Controller::calculate_targets() {
84
    Controller::motion_generator_vector_t::iterator it;
85 ea068cf1 sschulz
    for (it = motion_generator_vector_.begin(); it < motion_generator_vector_.end(); it++) {
86 2aa96942 sschulz
        MotionGenerator *mg = *it;
87
        // calculate targets
88
        mg->calculate_targets();
89 8c6c1163 Simon Schulz
    }
90
}
91
92 2aa96942 sschulz
debug_data_t Controller::get_debug_data() {
93
    debug_data_t debug_data;
94
95
    Controller::motion_generator_vector_t::iterator it;
96
    for (it = motion_generator_vector_.begin(); it < motion_generator_vector_.end(); it++) {
97
        MotionGenerator *mg = *it;
98
        // fetch and append debug data
99
        debug_data_t dataset = mg->get_debug_data();
100
        debug_data.insert(dataset.begin(), dataset.end());
101
    }
102
103
    return debug_data;
104
}
105
106 8c6c1163 Simon Schulz
//! publish all target angles to the devices:
107
//! NOTE: this is done in an extra loop to have a low delay between consequent sets:
108 0c8d22a5 sschulz
void Controller::publish_targets() {
109
    Controller::motion_generator_vector_t::iterator it;
110 ea068cf1 sschulz
    for (it = motion_generator_vector_.begin(); it < motion_generator_vector_.end(); it++) {
111 8c6c1163 Simon Schulz
        (*it)->publish_targets();
112
    }
113
}
114
115 0c8d22a5 sschulz
humotion::GazeState Controller::relative_gaze_to_absolute_gaze(humotion::GazeState relative) {
116 caf7373f Simon Schulz
    double pan, tilt, roll;
117 0c8d22a5 sschulz
    humotion::GazeState absolute_gaze = relative;
118 89374d69 Simon Schulz
119 0c8d22a5 sschulz
    // incoming gaze state wants to set a relative gaze angle
120
    // in order to calc the new absolute gaze, we need to go back
121
    // in time and find out where the head was pointing at that specific time:
122 32327f15 Simon Schulz
    Timestamp relative_target_timestamp = relative.timestamp;
123 89374d69 Simon Schulz
124 0c8d22a5 sschulz
    // check if this timestamp allows a valid conversion:
125
    Timestamp history_begin =
126 ea068cf1 sschulz
            joint_interface_->get_ts_position(JointInterface::ID_NECK_PAN).get_first_timestamp();
127 0c8d22a5 sschulz
    // Timestamp history_end   =
128
    //       joint_interface->get_ts_position(JointInterface::ID_NECK_PAN).get_last_timestamp();
129
130
    // printf("> incoming: %f, history is %f to %f\n",relative_target_timestamp.to_seconds(),
131
    // history_begin.to_seconds(), history_end.to_seconds());
132
133
    // our history keeps the last n elements in a timestamped list
134
    if ((relative_target_timestamp < history_begin) || (history_begin.is_null())) {
135
        // when the incoming data is older than that it makes no sense
136
        // to do any guesswork and try to calculate a valid absolute target
137
        // therefore we will use the last known targets (see below)
138
        // in case we did not see this timestamp before, show a warning:
139 ea068cf1 sschulz
        if (last_known_absolute_timestamp_ != relative_target_timestamp) {
140 0c8d22a5 sschulz
            printf("> WARNING: restored/guessed absolute target for unknown timestamp %f "
141
                   "[this should not happen]\n", relative_target_timestamp.to_seconds());
142 ea068cf1 sschulz
            last_known_absolute_target_pan_ = 0.0;
143
            last_known_absolute_target_tilt_ = 0.0;
144
            last_known_absolute_target_roll_ = 0.0;
145 caf7373f Simon Schulz
        }
146 0c8d22a5 sschulz
    } else {
147
        // all fine, we can reconstruct the absolute target
148
        // fetch head / camera pose during that timestamp
149 ea068cf1 sschulz
        double neck_pan  = joint_interface_->get_ts_position(
150 0c8d22a5 sschulz
                JointInterface::ID_NECK_PAN).get_interpolated_value(relative_target_timestamp);
151 ea068cf1 sschulz
        double eye_l_pan = joint_interface_->get_ts_position(
152 0c8d22a5 sschulz
                JointInterface::ID_EYES_LEFT_LR).get_interpolated_value(relative_target_timestamp);
153 ea068cf1 sschulz
        double eye_r_pan = joint_interface_->get_ts_position(
154 0c8d22a5 sschulz
                JointInterface::ID_EYES_RIGHT_LR).get_interpolated_value(relative_target_timestamp);
155 ea068cf1 sschulz
        last_known_absolute_target_pan_       = neck_pan + (eye_l_pan + eye_r_pan)/2.0;
156 caf7373f Simon Schulz
        //
157 ea068cf1 sschulz
        double neck_tilt = joint_interface_->get_ts_position(
158 0c8d22a5 sschulz
                JointInterface::ID_NECK_TILT).get_interpolated_value(relative_target_timestamp);
159 ea068cf1 sschulz
        double eye_tilt  = joint_interface_->get_ts_position(
160 0c8d22a5 sschulz
                JointInterface::ID_EYES_BOTH_UD).get_interpolated_value(relative_target_timestamp);
161 ea068cf1 sschulz
        last_known_absolute_target_tilt_      = neck_tilt + eye_tilt;
162 caf7373f Simon Schulz
        //
163 ea068cf1 sschulz
        last_known_absolute_target_roll_      = joint_interface_->get_ts_position(
164 0c8d22a5 sschulz
                JointInterface::ID_NECK_ROLL).get_interpolated_value(relative_target_timestamp);
165
166
        // safe this timestamp as known:
167 ea068cf1 sschulz
        last_known_absolute_timestamp_ = relative_target_timestamp;
168 caf7373f Simon Schulz
    }
169
170 ea068cf1 sschulz
    pan  = last_known_absolute_target_pan_;
171
    tilt = last_known_absolute_target_tilt_;
172
    roll = last_known_absolute_target_roll_;
173 89374d69 Simon Schulz
174 0c8d22a5 sschulz
    // substract offsets
175 caf7373f Simon Schulz
    pan  -= relative.pan_offset;
176 d82702d2 Sebastian Meyer zu Borgsen
    tilt -= relative.tilt_offset;
177
    roll -= relative.roll_offset;
178
179 3d980d8f Sebastian Meyer zu Borgsen
180 0c8d22a5 sschulz
    // build up absolute target
181 1c758459 Simon Schulz
    absolute_gaze.gaze_type  = GazeState::GAZETYPE_ABSOLUTE;
182 89374d69 Simon Schulz
    absolute_gaze.pan   = pan + relative.pan;
183
    absolute_gaze.tilt  = tilt + relative.tilt;
184
    absolute_gaze.roll  = roll + relative.roll;
185 0c8d22a5 sschulz
    printf("pan  now = %4.1f, rel=%4.1f ===> %4.2f\n", pan, relative.pan, absolute_gaze.pan);
186
    printf("tilt now = %4.1f, rel=%4.1f ===> %4.2f\n", tilt, relative.tilt, absolute_gaze.tilt);
187 89374d69 Simon Schulz
188 0c8d22a5 sschulz
    // FIXME: use ros TF for that calculation...
189
    // see http://wiki.ros.org/tf/Tutorials/Time%20travel%20with%20tf%20%28C%2B%2B%29
190
    // ros::Time past = now - ros::Duration(5.0);
191
    // listener.waitForTransform("/turtle2", now,J "/turtle1", past, "/world", ros::Duration(1.0));
192
    // listener.lookupTransform("/turtle2", now, "/turtle1", past, "/world", transform);
193
    // absolute_gaze.dump();
194 caf7373f Simon Schulz
195 89374d69 Simon Schulz
    return absolute_gaze;
196
}
197
198 5d7ba19c Simon Schulz
//! activate controller
199 0c8d22a5 sschulz
void Controller::set_activated(void) {
200 ea068cf1 sschulz
    activated_ = true;
201 5d7ba19c Simon Schulz
}
202 8c6c1163 Simon Schulz
203
//! update gaze target:
204
//! \param GazeState with target values for the overall gaze
205 0c8d22a5 sschulz
void Controller::set_gaze_target(humotion::GazeState new_gaze_target) {
206 ea068cf1 sschulz
    if (!activated_) {
207 0c8d22a5 sschulz
        // not yet initialized, ignore incoming targets
208 5d7ba19c Simon Schulz
        return;
209
    }
210
211 0c8d22a5 sschulz
    humotion::GazeState target_gaze;
212
    // new_gaze_target.dump();
213 89374d69 Simon Schulz
214 0c8d22a5 sschulz
    // relative or absolute gaze update?
215
    if (new_gaze_target.gaze_type == GazeState::GAZETYPE_RELATIVE) {
216
        // relative gaze target -> calculate target angles
217 89374d69 Simon Schulz
        target_gaze = relative_gaze_to_absolute_gaze(new_gaze_target);
218 0c8d22a5 sschulz
    } else {
219
        // already absolute gaze, set this
220 89374d69 Simon Schulz
        target_gaze = new_gaze_target;
221
    }
222
223 0c8d22a5 sschulz
    Controller::motion_generator_vector_t::iterator it;
224 ea068cf1 sschulz
    for (it = motion_generator_vector_.begin(); it < motion_generator_vector_.end(); it++) {
225 89374d69 Simon Schulz
        (*it)->set_gaze_target(target_gaze);
226 8c6c1163 Simon Schulz
    }
227
}
228
229
//! update mouth state:
230
//! \param MouthState with target values for the mouth joints
231 0c8d22a5 sschulz
void Controller::set_mouth_target(MouthState s) {
232 ea068cf1 sschulz
    if (!activated_) {
233 0c8d22a5 sschulz
        // not yet initialized, ignore incoming targets
234 5d7ba19c Simon Schulz
        return;
235
    }
236
237 0c8d22a5 sschulz
    Controller::motion_generator_vector_t::iterator it;
238 ea068cf1 sschulz
    for (it = motion_generator_vector_.begin(); it < motion_generator_vector_.end(); it++) {
239 8c6c1163 Simon Schulz
        (*it)->set_mouth_target(s);
240
    }
241
}
242 277050c7 sschulz
243
//! access the configuration
244
Config* Controller::get_config() {
245
    return config_;
246
}