Statistics
| Branch: | Tag: | Revision:

humotion / examples / yarp_icub / src / icub_data_receiver.cpp @ 51a1f01d

History | View | Annotate | Download (9.269 KB)

1 6a2d467f 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
#include <boost/format.hpp>
29 35b3ca25 Simon Schulz
#include <humotion/server/joint_interface.h>
30 8c6c1163 Simon Schulz
#include <yarp/os/Property.h>
31 6a2d467f Simon Schulz
32 a5cc61d4 sschulz
#include <string>
33
34 6a2d467f Simon Schulz
#include "humotion_yarp_icub/icub_data_receiver.h"
35 ad7b6f18 Simon Schulz
36 35b3ca25 Simon Schulz
using std::cout;
37 1f748ce7 Simon Schulz
using std::cerr;
38 35b3ca25 Simon Schulz
using std::string;
39 25400c71 sschulz
40 35b3ca25 Simon Schulz
using humotion::server::JointInterface;
41 25400c71 sschulz
using humotion::Timestamp;
42
43 35b3ca25 Simon Schulz
using yarp::dev::IEncodersTimed;
44
using yarp::sig::Vector;
45
46 ea29304b Simon Schulz
#define ICUB_DATA_RECEIVER_USE_ENCODERSPEED 0
47 ad7b6f18 Simon Schulz
#define ICUB_DATA_RECEIVER_DUMP_DATA 0
48 ea29304b Simon Schulz
49 ad7b6f18 Simon Schulz
//! constructor
50
//! \param period_ms for the yarp rate thread
51
//! \param icub_jointinterface
52
iCubDataReceiver::iCubDataReceiver(int period_ms, iCubJointInterface *icub_jointinterface)
53
    : yarp::os::RateThread(period_ms) {
54 35b3ca25 Simon Schulz
55
    // store pointer to icub jointinterface
56
    icub_jointinterface_ = icub_jointinterface;
57
58 6a2d467f Simon Schulz
    // fetch iencs view from yarp
59 35b3ca25 Simon Schulz
    yarp::dev::PolyDriver *poly_driver = icub_jointinterface->get_yarp_polydriver();
60 ea29304b Simon Schulz
    bool success = poly_driver->view(iencs_);
61 35b3ca25 Simon Schulz
    if (!success) {
62 1f748ce7 Simon Schulz
        cerr << "ERROR: polydriver failed to init iencs view\n";
63 35b3ca25 Simon Schulz
        exit(EXIT_FAILURE);
64
    }
65
66 ea29304b Simon Schulz
    // resize data storage vectors to match the number of axes
67 8c6c1163 Simon Schulz
    int joints;
68 ea29304b Simon Schulz
    iencs_->getAxes(&joints);
69
    positions_.resize(joints);
70
    velocities_.resize(joints);
71
    timestamps_.resize(joints);
72 8c6c1163 Simon Schulz
}
73
74 ad7b6f18 Simon Schulz
//! yarp rate thread initializer
75 35b3ca25 Simon Schulz
bool iCubDataReceiver::threadInit() {
76
    return true;
77 8c6c1163 Simon Schulz
}
78
79 ad7b6f18 Simon Schulz
//! yarp thread release function
80 35b3ca25 Simon Schulz
void iCubDataReceiver::threadRelease() {
81
}
82 7adf90be Simon Schulz
83 ad7b6f18 Simon Schulz
//! manully calculate joint velocities (instead of using joint encoder speeds)
84
//! \param positions vector with current encoder position
85
//! \param timestamps vector with the associated timestamps
86
//! \return velocities as vector
87 1f748ce7 Simon Schulz
Vector iCubDataReceiver::calculate_velocities(Vector positions, Vector timestamps) {
88
    Vector velocities;
89 ea29304b Simon Schulz
    velocities.resize(positions.size());
90
91 6a2d467f Simon Schulz
    if (previous_positions_.size() == 0) {
92 ea29304b Simon Schulz
        // first run, no valid old position available, return zero velocities
93
        // by setting all all elements to zero
94
        velocities = 0.0;
95 6a2d467f Simon Schulz
    } else {
96 ea29304b Simon Schulz
        // calculate speed based on positions:
97 6a2d467f Simon Schulz
        for (int i=0; i < positions.size(); i++) {
98 ea29304b Simon Schulz
            float diff = positions[i] - previous_positions_[i];
99
            float timediff = timestamps[i] - previous_timestamps_[i];
100
            // calc speed:
101
            velocities[i] = diff / timediff;
102
        }
103
    }
104
105
    previous_positions_ = positions;
106
    previous_timestamps_ = timestamps;
107
108
    return velocities;
109
}
110
111 ad7b6f18 Simon Schulz
//! main loop routine, called by yarp rate thread
112 35b3ca25 Simon Schulz
void iCubDataReceiver::run() {
113 ea29304b Simon Schulz
    float velocity;
114 25400c71 sschulz
    Timestamp timestamp;
115 ea29304b Simon Schulz
116 6a2d467f Simon Schulz
    // grab pos+vel data:
117 ea29304b Simon Schulz
    iencs_->getEncodersTimed(positions_.data(), timestamps_.data());
118 8c6c1163 Simon Schulz
119 ea29304b Simon Schulz
    #if ICUB_DATA_RECEIVER_USE_ENCODERSPEED
120
    // fetch data from icub. NOTE: make sure to enable the vel broadcast in the ini file!
121 6a2d467f Simon Schulz
    if (!iencs_->getEncoderSpeeds(velocities_.data())) {
122 18e9b892 Simon Schulz
        cout << "Failed to fetch encoder speeds...\n";
123
        return;
124
    }
125 ea29304b Simon Schulz
    #else
126
    // manually calculate the speed based on old position:
127
    velocities_ = calculate_velocities(positions_, timestamps_);
128
    #endif
129
130
    // publish data to humotion
131 6a2d467f Simon Schulz
    for (int i = 0; i < positions_.size(); i++) {
132 25400c71 sschulz
        // convert to humotion timestamp
133
        timestamp = Timestamp(timestamps_[i]);
134 ea29304b Simon Schulz
        // store position values
135 25400c71 sschulz
        store_incoming_position(i, positions_[i], timestamp);
136 ea29304b Simon Schulz
        // store velocity
137 25400c71 sschulz
        store_incoming_velocity(i, velocities_[i], timestamp);
138 8c6c1163 Simon Schulz
    }
139 6a2d467f Simon Schulz
140
    // small hack to tell humotion to update the lid angle
141
    // fixme: use real id
142 25400c71 sschulz
    timestamp = Timestamp::now();
143
    store_incoming_position(100, 0.0, timestamp);
144 ad7b6f18 Simon Schulz
145
    #if ICUB_DATA_RECEIVER_DUMP_DATA
146
    dump_incoming_data();
147
    #endif
148 35b3ca25 Simon Schulz
}
149
150 ad7b6f18 Simon Schulz
//! store incoming position for a given icub joint
151
//! \param icub _id icub joint id
152
//! \param position
153
//! \param timestamp
154 25400c71 sschulz
void iCubDataReceiver::store_incoming_position(int icub_id, double position, Timestamp timestamp) {
155 a5cc61d4 sschulz
    // cout << "store_incoming_position(icub=" << icub_id << ", " << position << ")\n";
156 6c028e11 Simon Schulz
157 35b3ca25 Simon Schulz
    // store joint position in humotion backend
158
    if ((icub_id == iCubJointInterface::ICUB_ID_EYES_PAN) ||
159
            (icub_id == iCubJointInterface::ICUB_ID_EYES_VERGENCE)) {
160
        // the icub handles eyes differently
161
        // instead of using seperate left/right pan the icub uses
162
        // a combined pan angle and vergence. therfore we have to convert this here:
163
        if (icub_id == iCubJointInterface::ICUB_ID_EYES_PAN) {
164 ad7b6f18 Simon Schulz
            target_eye_pan_ = position;
165 35b3ca25 Simon Schulz
        } else {
166 ad7b6f18 Simon Schulz
            target_eye_vergence_ = -position;
167 35b3ca25 Simon Schulz
        }
168
169 18e9b892 Simon Schulz
        float right = target_eye_pan_ + target_eye_vergence_/2.0;
170
        float left  = target_eye_pan_ - target_eye_vergence_/2.0;
171 35b3ca25 Simon Schulz
172
        icub_jointinterface_->store_incoming_position(JointInterface::ID_EYES_LEFT_LR,
173
                                                     left, timestamp);
174
        icub_jointinterface_->store_incoming_position(JointInterface::ID_EYES_RIGHT_LR,
175
                                                     right, timestamp);
176
    } else if (icub_id == 100) {
177 25400c71 sschulz
        // HACK
178 a5cc61d4 sschulz
        // icub_jointinterface->store_incoming_position(ID_EYES_RIGHT_LID_UPPER,
179 35b3ca25 Simon Schulz
        //                                             lid_angle, timestamp);
180
    } else {
181 6c028e11 Simon Schulz
        if (icub_id == iCubJointInterface::ID_NECK_PAN) {
182
            // icub uses an inverted neck pan specification
183 ad7b6f18 Simon Schulz
            position = -position;
184 6c028e11 Simon Schulz
        }
185
186 35b3ca25 Simon Schulz
        // known configured mapping between joint ids
187
        int humotion_id = icub_jointinterface_->convert_icub_jointid_to_humotion(icub_id);
188 ad7b6f18 Simon Schulz
        icub_jointinterface_->store_incoming_position(humotion_id, position, timestamp);
189 35b3ca25 Simon Schulz
    }
190 8c6c1163 Simon Schulz
}
191 ea29304b Simon Schulz
192 ad7b6f18 Simon Schulz
//! store incoming velocity for a given icub joint
193
//! \param icub_id icub joint id
194
//! \param velocity
195
//! \param timestamp
196 25400c71 sschulz
void iCubDataReceiver::store_incoming_velocity(int icub_id, double velocity, Timestamp timestamp) {
197 a5cc61d4 sschulz
    // cout << "store_incoming_velocity(icub=" << icub_id << ", " << velocity << ")\n";
198 ea29304b Simon Schulz
199
    // store joint position in humotion backend
200
    if ((icub_id == iCubJointInterface::ICUB_ID_EYES_PAN) ||
201
            (icub_id == iCubJointInterface::ICUB_ID_EYES_VERGENCE)) {
202
        // the icub handles eyes differently
203
        // instead of using seperate left/right pan the icub uses
204
        // a combined pan angle and vergence. therfore we have to convert this here:
205
        if (icub_id == iCubJointInterface::ICUB_ID_EYES_PAN) {
206
            target_eye_pan_velocity_ = velocity;
207
        } else {
208
            target_eye_vergence_velocity_ = -velocity;
209
        }
210
211 18e9b892 Simon Schulz
        float right = target_eye_pan_velocity_ + target_eye_vergence_velocity_/2.0;
212
        float left  = target_eye_pan_velocity_ - target_eye_vergence_velocity_/2.0;
213 ea29304b Simon Schulz
214
        icub_jointinterface_->store_incoming_velocity(JointInterface::ID_EYES_LEFT_LR,
215
                                                     left, timestamp);
216
        icub_jointinterface_->store_incoming_velocity(JointInterface::ID_EYES_RIGHT_LR,
217
                                                     right, timestamp);
218
    } else if (icub_id == 100) {
219 25400c71 sschulz
        // HACK
220 a5cc61d4 sschulz
        // icub_jointinterface->store_incoming_position(ID_EYES_RIGHT_LID_UPPER,
221 ea29304b Simon Schulz
        //                                             lid_angle, timestamp);
222
    } else {
223
        if (icub_id == iCubJointInterface::ID_NECK_PAN) {
224
            // icub uses an inverted neck pan specification
225
            velocity = -velocity;
226
        }
227
228
        // known configured mapping between joint ids
229
        int humotion_id = icub_jointinterface_->convert_icub_jointid_to_humotion(icub_id);
230
        icub_jointinterface_->store_incoming_velocity(humotion_id, velocity, timestamp);
231
    }
232
}
233
234 ad7b6f18 Simon Schulz
//! helper for debugging purposes, feed this data into gnuplot for visual inspection
235
void iCubDataReceiver::dump_incoming_data() {
236
    // use gnuplot for viz:
237
    // ./icub_humotion_server --robot icub | grep "INCOMING" |tee  log
238
    // @gnuplot: plot "log" using 0:1 w l t "p neck tilt", "log" using 0:2 w l t "v neck tilt", \
239
    //                "log" using 0:5 w l t "p neck pan", "log" using 0:6 w l t "v neck pan", \
240
    //                "log" using 0:7 w l t "p eyes ud", "log" using 0:8 w l t "v eyes ud", \
241 a5cc61d4 sschulz
    //                "log" using 0:9 w l t "p eyes vergence", "log" using 0:10 w l t "v eyes verg"
242 ad7b6f18 Simon Schulz
    cout << "\n";
243
            // publish data to humotion
244 a5cc61d4 sschulz
    for (int i = 0; i < positions_.size(); i++) {
245 ad7b6f18 Simon Schulz
        cout << positions_[i] << " ";
246
        cout << velocities_[i] << " ";
247
    }
248
    cout << " #INCOMING_DATA_DUMP\n";
249
}
250