Statistics
| Branch: | Tag: | Revision:

humotion / examples / yarp_icub / src / icub_data_receiver.cpp @ 14831938

History | View | Annotate | Download (9.269 KB)

1
/*
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
#include <humotion/server/joint_interface.h>
30
#include <yarp/os/Property.h>
31

    
32
#include <string>
33

    
34
#include "humotion_yarp_icub/icub_data_receiver.h"
35

    
36
using std::cout;
37
using std::cerr;
38
using std::string;
39

    
40
using humotion::server::JointInterface;
41
using humotion::Timestamp;
42

    
43
using yarp::dev::IEncodersTimed;
44
using yarp::sig::Vector;
45

    
46
#define ICUB_DATA_RECEIVER_USE_ENCODERSPEED 0
47
#define ICUB_DATA_RECEIVER_DUMP_DATA 0
48

    
49
//! 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

    
55
    // store pointer to icub jointinterface
56
    icub_jointinterface_ = icub_jointinterface;
57

    
58
    // fetch iencs view from yarp
59
    yarp::dev::PolyDriver *poly_driver = icub_jointinterface->get_yarp_polydriver();
60
    bool success = poly_driver->view(iencs_);
61
    if (!success) {
62
        cerr << "ERROR: polydriver failed to init iencs view\n";
63
        exit(EXIT_FAILURE);
64
    }
65

    
66
    // resize data storage vectors to match the number of axes
67
    int joints;
68
    iencs_->getAxes(&joints);
69
    positions_.resize(joints);
70
    velocities_.resize(joints);
71
    timestamps_.resize(joints);
72
}
73

    
74
//! yarp rate thread initializer
75
bool iCubDataReceiver::threadInit() {
76
    return true;
77
}
78

    
79
//! yarp thread release function
80
void iCubDataReceiver::threadRelease() {
81
}
82

    
83
//! 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
Vector iCubDataReceiver::calculate_velocities(Vector positions, Vector timestamps) {
88
    Vector velocities;
89
    velocities.resize(positions.size());
90

    
91
    if (previous_positions_.size() == 0) {
92
        // first run, no valid old position available, return zero velocities
93
        // by setting all all elements to zero
94
        velocities = 0.0;
95
    } else {
96
        // calculate speed based on positions:
97
        for (int i=0; i < positions.size(); i++) {
98
            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
//! main loop routine, called by yarp rate thread
112
void iCubDataReceiver::run() {
113
    float velocity;
114
    Timestamp timestamp;
115

    
116
    // grab pos+vel data:
117
    iencs_->getEncodersTimed(positions_.data(), timestamps_.data());
118

    
119
    #if ICUB_DATA_RECEIVER_USE_ENCODERSPEED
120
    // fetch data from icub. NOTE: make sure to enable the vel broadcast in the ini file!
121
    if (!iencs_->getEncoderSpeeds(velocities_.data())) {
122
        cout << "Failed to fetch encoder speeds...\n";
123
        return;
124
    }
125
    #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
    for (int i = 0; i < positions_.size(); i++) {
132
        // convert to humotion timestamp
133
        timestamp = Timestamp(timestamps_[i]);
134
        // store position values
135
        store_incoming_position(i, positions_[i], timestamp);
136
        // store velocity
137
        store_incoming_velocity(i, velocities_[i], timestamp);
138
    }
139

    
140
    // small hack to tell humotion to update the lid angle
141
    // fixme: use real id
142
    timestamp = Timestamp::now();
143
    store_incoming_position(100, 0.0, timestamp);
144

    
145
    #if ICUB_DATA_RECEIVER_DUMP_DATA
146
    dump_incoming_data();
147
    #endif
148
}
149

    
150
//! store incoming position for a given icub joint
151
//! \param icub _id icub joint id
152
//! \param position
153
//! \param timestamp
154
void iCubDataReceiver::store_incoming_position(int icub_id, double position, Timestamp timestamp) {
155
    // cout << "store_incoming_position(icub=" << icub_id << ", " << position << ")\n";
156

    
157
    // 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
            target_eye_pan_ = position;
165
        } else {
166
            target_eye_vergence_ = -position;
167
        }
168

    
169
        float right = target_eye_pan_ + target_eye_vergence_/2.0;
170
        float left  = target_eye_pan_ - target_eye_vergence_/2.0;
171

    
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
        // HACK
178
        // icub_jointinterface->store_incoming_position(ID_EYES_RIGHT_LID_UPPER,
179
        //                                             lid_angle, timestamp);
180
    } else {
181
        if (icub_id == iCubJointInterface::ID_NECK_PAN) {
182
            // icub uses an inverted neck pan specification
183
            position = -position;
184
        }
185

    
186
        // known configured mapping between joint ids
187
        int humotion_id = icub_jointinterface_->convert_icub_jointid_to_humotion(icub_id);
188
        icub_jointinterface_->store_incoming_position(humotion_id, position, timestamp);
189
    }
190
}
191

    
192
//! store incoming velocity for a given icub joint
193
//! \param icub_id icub joint id
194
//! \param velocity
195
//! \param timestamp
196
void iCubDataReceiver::store_incoming_velocity(int icub_id, double velocity, Timestamp timestamp) {
197
    // cout << "store_incoming_velocity(icub=" << icub_id << ", " << velocity << ")\n";
198

    
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
        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

    
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
        // HACK
220
        // icub_jointinterface->store_incoming_position(ID_EYES_RIGHT_LID_UPPER,
221
        //                                             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
//! 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
    //                "log" using 0:9 w l t "p eyes vergence", "log" using 0:10 w l t "v eyes verg"
242
    cout << "\n";
243
            // publish data to humotion
244
    for (int i = 0; i < positions_.size(); i++) {
245
        cout << positions_[i] << " ";
246
        cout << velocities_[i] << " ";
247
    }
248
    cout << " #INCOMING_DATA_DUMP\n";
249
}
250

    
251