Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (9.104 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
using humotion::server::JointInterface;
40
using yarp::dev::IEncodersTimed;
41
using yarp::sig::Vector;
42

    
43
#define ICUB_DATA_RECEIVER_USE_ENCODERSPEED 0
44
#define ICUB_DATA_RECEIVER_DUMP_DATA 0
45

    
46
//! constructor
47
//! \param period_ms for the yarp rate thread
48
//! \param icub_jointinterface
49
iCubDataReceiver::iCubDataReceiver(int period_ms, iCubJointInterface *icub_jointinterface)
50
    : yarp::os::RateThread(period_ms) {
51

    
52
    // store pointer to icub jointinterface
53
    icub_jointinterface_ = icub_jointinterface;
54

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

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

    
71
//! yarp rate thread initializer
72
bool iCubDataReceiver::threadInit() {
73
    return true;
74
}
75

    
76
//! yarp thread release function
77
void iCubDataReceiver::threadRelease() {
78
}
79

    
80
//! manully calculate joint velocities (instead of using joint encoder speeds)
81
//! \param positions vector with current encoder position
82
//! \param timestamps vector with the associated timestamps
83
//! \return velocities as vector
84
Vector iCubDataReceiver::calculate_velocities(Vector positions, Vector timestamps) {
85
    Vector velocities;
86
    velocities.resize(positions.size());
87

    
88
    if (previous_positions_.size() == 0) {
89
        // first run, no valid old position available, return zero velocities
90
        // by setting all all elements to zero
91
        velocities = 0.0;
92
    } else {
93
        // calculate speed based on positions:
94
        for (int i=0; i < positions.size(); i++) {
95
            float diff = positions[i] - previous_positions_[i];
96
            float timediff = timestamps[i] - previous_timestamps_[i];
97
            // calc speed:
98
            velocities[i] = diff / timediff;
99
        }
100
    }
101

    
102
    previous_positions_ = positions;
103
    previous_timestamps_ = timestamps;
104

    
105
    return velocities;
106
}
107

    
108
//! main loop routine, called by yarp rate thread
109
void iCubDataReceiver::run() {
110
    float velocity;
111

    
112
    // grab pos+vel data:
113
    iencs_->getEncodersTimed(positions_.data(), timestamps_.data());
114

    
115
    #if ICUB_DATA_RECEIVER_USE_ENCODERSPEED
116
    // fetch data from icub. NOTE: make sure to enable the vel broadcast in the ini file!
117
    if (!iencs_->getEncoderSpeeds(velocities_.data())) {
118
        cout << "Failed to fetch encoder speeds...\n";
119
        return;
120
    }
121
    #else
122
    // manually calculate the speed based on old position:
123
    velocities_ = calculate_velocities(positions_, timestamps_);
124
    #endif
125

    
126
    // publish data to humotion
127
    for (int i = 0; i < positions_.size(); i++) {
128
        // store position values
129
        store_incoming_position(i, positions_[i], timestamps_[i]);
130
        // store velocity
131
        store_incoming_velocity(i, velocities_[i], timestamps_[i]);
132
    }
133

    
134
    // small hack to tell humotion to update the lid angle
135
    // fixme: use real id
136
    store_incoming_position(100, 0.0, timestamps_[0]);
137

    
138
    #if ICUB_DATA_RECEIVER_DUMP_DATA
139
    dump_incoming_data();
140
    #endif
141
}
142

    
143
//! store incoming position for a given icub joint
144
//! \param icub _id icub joint id
145
//! \param position
146
//! \param timestamp
147
void iCubDataReceiver::store_incoming_position(int icub_id, double position, double timestamp) {
148
    // cout << "store_incoming_position(icub=" << icub_id << ", " << position << ")\n";
149

    
150
    // store joint position in humotion backend
151
    if ((icub_id == iCubJointInterface::ICUB_ID_EYES_PAN) ||
152
            (icub_id == iCubJointInterface::ICUB_ID_EYES_VERGENCE)) {
153
        // the icub handles eyes differently
154
        // instead of using seperate left/right pan the icub uses
155
        // a combined pan angle and vergence. therfore we have to convert this here:
156
        if (icub_id == iCubJointInterface::ICUB_ID_EYES_PAN) {
157
            target_eye_pan_ = position;
158
        } else {
159
            target_eye_vergence_ = -position;
160
        }
161

    
162
        float right = target_eye_pan_ + target_eye_vergence_/2.0;
163
        float left  = target_eye_pan_ - target_eye_vergence_/2.0;
164

    
165
        icub_jointinterface_->store_incoming_position(JointInterface::ID_EYES_LEFT_LR,
166
                                                     left, timestamp);
167
        icub_jointinterface_->store_incoming_position(JointInterface::ID_EYES_RIGHT_LR,
168
                                                     right, timestamp);
169
    } else if (icub_id == 100) {
170
        //HACK
171
        // icub_jointinterface->store_incoming_position(ID_EYES_RIGHT_LID_UPPER,
172
        //                                             lid_angle, timestamp);
173
    } else {
174
        if (icub_id == iCubJointInterface::ID_NECK_PAN) {
175
            // icub uses an inverted neck pan specification
176
            position = -position;
177
        }
178

    
179
        // known configured mapping between joint ids
180
        int humotion_id = icub_jointinterface_->convert_icub_jointid_to_humotion(icub_id);
181
        icub_jointinterface_->store_incoming_position(humotion_id, position, timestamp);
182
    }
183
}
184

    
185
//! store incoming velocity for a given icub joint
186
//! \param icub_id icub joint id
187
//! \param velocity
188
//! \param timestamp
189
void iCubDataReceiver::store_incoming_velocity(int icub_id, double velocity, double timestamp) {
190
    // cout << "store_incoming_velocity(icub=" << icub_id << ", " << velocity << ")\n";
191

    
192
    // store joint position in humotion backend
193
    if ((icub_id == iCubJointInterface::ICUB_ID_EYES_PAN) ||
194
            (icub_id == iCubJointInterface::ICUB_ID_EYES_VERGENCE)) {
195
        // the icub handles eyes differently
196
        // instead of using seperate left/right pan the icub uses
197
        // a combined pan angle and vergence. therfore we have to convert this here:
198
        if (icub_id == iCubJointInterface::ICUB_ID_EYES_PAN) {
199
            target_eye_pan_velocity_ = velocity;
200
        } else {
201
            target_eye_vergence_velocity_ = -velocity;
202
        }
203

    
204
        float right = target_eye_pan_velocity_ + target_eye_vergence_velocity_/2.0;
205
        float left  = target_eye_pan_velocity_ - target_eye_vergence_velocity_/2.0;
206

    
207
        icub_jointinterface_->store_incoming_velocity(JointInterface::ID_EYES_LEFT_LR,
208
                                                     left, timestamp);
209
        icub_jointinterface_->store_incoming_velocity(JointInterface::ID_EYES_RIGHT_LR,
210
                                                     right, timestamp);
211
    } else if (icub_id == 100) {
212
        //HACK
213
        // icub_jointinterface->store_incoming_position(ID_EYES_RIGHT_LID_UPPER,
214
        //                                             lid_angle, timestamp);
215
    } else {
216
        if (icub_id == iCubJointInterface::ID_NECK_PAN) {
217
            // icub uses an inverted neck pan specification
218
            velocity = -velocity;
219
        }
220

    
221
        // known configured mapping between joint ids
222
        int humotion_id = icub_jointinterface_->convert_icub_jointid_to_humotion(icub_id);
223
        icub_jointinterface_->store_incoming_velocity(humotion_id, velocity, timestamp);
224
    }
225
}
226

    
227
//! helper for debugging purposes, feed this data into gnuplot for visual inspection
228
void iCubDataReceiver::dump_incoming_data() {
229
    // use gnuplot for viz:
230
    // ./icub_humotion_server --robot icub | grep "INCOMING" |tee  log
231
    // @gnuplot: plot "log" using 0:1 w l t "p neck tilt", "log" using 0:2 w l t "v neck tilt", \
232
    //                "log" using 0:5 w l t "p neck pan", "log" using 0:6 w l t "v neck pan", \
233
    //                "log" using 0:7 w l t "p eyes ud", "log" using 0:8 w l t "v eyes ud", \
234
    //                "log" using 0:9 w l t "p eyes vergence", "log" using 0:10 w l t "v eyes verg"
235
    cout << "\n";
236
            // publish data to humotion
237
    for (int i = 0; i < positions_.size(); i++) {
238
        cout << positions_[i] << " ";
239
        cout << velocities_[i] << " ";
240
    }
241
    cout << " #INCOMING_DATA_DUMP\n";
242
}
243

    
244