RobotsIO
Loading...
Searching...
No Matches
iCubHand.cpp
1/*
2 * Copyright (C) 2019 Istituto Italiano di Tecnologia (IIT)
3 *
4 * This software may be modified and distributed under the terms of the
5 * BSD 3-Clause license. See the accompanying LICENSE file for details.
6 */
7
8#include <RobotsIO/Hand/iCubHand.h>
9
10#include <yarp/eigen/Eigen.h>
11#include <yarp/os/Property.h>
12#include <yarp/os/ResourceFinder.h>
13#include <yarp/sig/Vector.h>
14
15#include <deque>
16#include <iostream>
17
18using namespace Eigen;
19using namespace RobotsIO::Hand;
20using namespace iCub::iKin;
21using namespace yarp::dev;
22using namespace yarp::eigen;
23using namespace yarp::os;
24using namespace yarp::sig;
25
26
27iCubHand::iCubHand
28(
29 const std::string& robot_name,
30 const std::string& laterality,
31 const std::string& port_prefix,
32 const std::string& context,
33 const bool& use_analogs,
34 const std::string& thumb_version
35) :
36 use_analogs_(use_analogs)
37{
38 /* Check YARP network. */
39 if (!yarp_.checkNetwork())
40 {
41 throw(std::runtime_error(log_name_ + "::ctor. Error: YARP network is not available."));
42 }
43
44 /* Check for laterality. */
45 if ((laterality != "right") && (laterality != "left"))
46 {
47 throw std::runtime_error(log_name_ + "::ctor. Error: invalid laterality" + laterality + ".");
48 }
49
50 if (use_analogs_)
51 {
52 /* Load configuration from config file. */
53 ResourceFinder rf;
54 rf.setVerbose(true);
55 rf.setDefaultConfigFile("icub_hand_configuration.ini");
56 rf.setDefaultContext(context);
57 rf.configure(0, NULL);
58
59 /* Get inner resource finder according to requested laterality. */
60 ResourceFinder inner_rf = rf.findNestedResourceFinder(laterality.c_str());
61 bool use_bounds_ = inner_rf.check("use_bounds", Value(false)).asBool();
62 if (use_bounds_)
63 {
64 bool valid_vector;
65 yarp::sig::Vector bounds_col_0;
66 std::tie(valid_vector, bounds_col_0) = load_vector_double(inner_rf, "bounds_col_0", 16);
67 if (!valid_vector)
68 {
69 throw std::runtime_error(log_name_ + "::ctor. Error: bounds requested but not available in the configuration file.");
70 }
71
72 yarp::sig::Vector bounds_col_1;
73 std::tie(valid_vector, bounds_col_1) = load_vector_double(inner_rf, "bounds_col_1", 16);
74 if (!valid_vector)
75 {
76 throw std::runtime_error(log_name_ + "::ctor. Error: bounds requested but not available in the configuration file.");
77 }
78
79 analog_bounds_.resize(16, 2);
80 analog_bounds_.setCol(0, bounds_col_0);
81 analog_bounds_.setCol(1, bounds_col_1);
82 }
83
84 /* Try to use PolyDriver for analogs. */
85 Property prop_analog;
86 prop_analog.put("device", "analogsensorclient");
87 prop_analog.put("local", "/" + port_prefix + "/" + laterality + "_hand/analog:i");
88 prop_analog.put("remote", "/" + robot_name + "/" + laterality + "_hand/analog:o");
89 if (drv_analog_.open(prop_analog))
90 {
91 /* Try to retrieve the view. */
92 if (drv_analog_.view(ianalog_) && ianalog_ != nullptr)
93 use_interface_analogs_ = true;
94 }
95
96 if (!use_interface_analogs_)
97 {
98 /* If the PolyDriver is not available, use a standard port. */
99 std::cout << log_name_ + "::ctor. Info: PolyDriver interface IAnalogSensors not available. Using raw encoders from a port." << std::endl;
100
101 if (!port_analogs_.open("/" + port_prefix + "/" + laterality + "_hand/analog:i"))
102 {
103 throw std::runtime_error(log_name_ + "::ctor. Error: unable to open port for analog encoders.");
104 }
105 }
106 }
107
108 /* Try to use PolyDriver for encoders. */
109 Property prop_encoders;
110 prop_encoders.put("device", "remote_controlboard");
111 prop_encoders.put("local", "/" + port_prefix + "/" + laterality + "_arm");
112 prop_encoders.put("remote", "/" + robot_name + "/" + laterality + "_arm");
113 if (drv_arm_.open(prop_encoders))
114 {
115 /* Try to retrieve the view. */
116 if (drv_arm_.view(iarm_) && iarm_ != nullptr)
117 use_interface_arm_ = true;
118
119 /* Try to retrieve the control limits view. */
120 if (!(drv_arm_.view(ilimits_)) || (ilimits_ == nullptr))
121 throw std::runtime_error(log_name_ + "::ctor. Error: unable get view for finger control limits.");
122 }
123
124 if (!use_interface_arm_)
125 {
126 /* If the PolyDriver is not available, use a standard port. */
127 std::cout << log_name_ + "::ctor. Info: PolyDriver interface IEncoders not available. Using raw encoders from a port." << std::endl;
128
129 if (!port_arm_.open("/" + port_prefix + "/" + laterality + "_arm"))
130 {
131 throw std::runtime_error(log_name_ + "::ctor. Error: unable to open port for arm encoders.");
132 }
133 }
134
135 /* Instantiate iCubFinger-s .*/
136 std::string thumb_key = "thumb";
137 if (!thumb_version.empty())
138 thumb_key += "_" + thumb_version;
139 fingers_["thumb"] = iCubFinger(laterality + "_" + thumb_key);
140 fingers_["index"] = iCubFinger(laterality + "_index");
141 fingers_["middle"] = iCubFinger(laterality + "_middle");
142 fingers_["ring"] = iCubFinger(laterality + "_ring");
143 fingers_["little"] = iCubFinger(laterality + "_little");
144
145 /* Align joint bounds using those of the real robot. */
146 if (ilimits_)
147 {
148 std::deque<IControlLimits*> limits;
149 limits.push_back(ilimits_);
150 for (auto& finger : fingers_)
151 finger.second.alignJointsBounds(limits);
152 }
153}
154
155
156iCubHand::~iCubHand()
157{
158 if (use_analogs_)
159 {
161 drv_analog_.close();
162 else
163 port_analogs_.close();
164 }
165
166 if (use_interface_arm_)
167 drv_arm_.close();
168 else
169 port_arm_.close();
170}
171
172
173std::pair<bool, std::unordered_map<std::string, Eigen::VectorXd>> iCubHand::encoders(const bool& blocking)
174{
175 /* Analog encoders. */
176 yarp::sig::Vector analogs(15);
177 bool outcome_analog = false;
178
179 if (use_analogs_)
180 {
182 outcome_analog = (ianalog_->read(analogs)) == (IAnalogSensor::AS_OK);
183 else
184 {
185 Bottle* bottle_analogs = port_analogs_.read(blocking);
186
187 if (bottle_analogs != nullptr)
188 {
189 for (size_t i = 0; i < analogs.size(); i++)
190 analogs(i) = bottle_analogs->get(i).asFloat64();
191
192 outcome_analog = true;
193 }
194 }
195 }
196
197 /* Arm encoders. */
198 yarp::sig::Vector encoders(9);
199
200 bool outcome_arm = false;
201
202 {
203 yarp::sig::Vector arm(16);
204
205 if (use_interface_arm_)
206 outcome_arm = iarm_->getEncoders(arm.data());
207 else
208 {
209 Bottle* bottle_arm = port_arm_.read(blocking);
210
211 if (bottle_arm != nullptr)
212 {
213 for (size_t i = 0; i < arm.size(); i++)
214 arm(i) = bottle_arm->get(i).asFloat64();
215
216 outcome_arm = true;
217 }
218 }
219
220 /* Get only part of arm encoders related to the fingers. */
221 toEigen(encoders) = toEigen(arm).segment<9>(7);
222 }
223
224 if (use_analogs_)
225 {
226 if (!(outcome_analog && outcome_arm))
227 return std::make_pair(false, std::unordered_map<std::string, VectorXd>());
228 }
229 else
230 {
231 if (!outcome_arm)
232 return std::make_pair(false, std::unordered_map<std::string, VectorXd>());
233 }
234
235 /* Combine arm and analog encoders. */
236 std::unordered_map<std::string, VectorXd> output_encoders;
237 for (auto& finger : fingers_)
238 {
239 yarp::sig::Vector chain_joints;
240 if (use_analogs_)
241 {
242 if (use_bounds_)
243 finger.second.getChainJoints(encoders, analogs, chain_joints, analog_bounds_);
244 else
245 finger.second.getChainJoints(encoders, analogs, chain_joints);
246 }
247 else
248 finger.second.getChainJoints(encoders, chain_joints);
249
250 VectorXd chain_joints_eigen = toEigen(chain_joints) * M_PI / 180.0;
251 output_encoders[finger.first] = chain_joints_eigen;
252 }
253
254 return std::make_pair(true, output_encoders);
255}
256
257
258std::pair<bool, yarp::sig::Vector> iCubHand::load_vector_double(const ResourceFinder& rf, const std::string key, const std::size_t size)
259{
260 bool ok = true;
261
262 if (rf.find(key).isNull())
263 ok = false;
264
265 Bottle* b = rf.find(key).asList();
266 if (b == nullptr)
267 ok = false;
268
269 if (b->size() != size)
270 ok = false;
271
272 if (!ok)
273 return std::make_pair(false, yarp::sig::Vector());
274
275 yarp::sig::Vector vector(size);
276 for (std::size_t i = 0; i < b->size(); i++)
277 {
278 Value item_v = b->get(i);
279 if (item_v.isNull())
280 return std::make_pair(false, yarp::sig::Vector());
281
282 if (!item_v.isFloat64())
283 return std::make_pair(false, yarp::sig::Vector());
284
285 vector(i) = item_v.asFloat64();
286 }
287
288 return std::make_pair(true, vector);
289}
std::unordered_map< std::string, iCub::iKin::iCubFinger > fingers_
Definition: iCubHand.h:83
yarp::dev::PolyDriver drv_analog_
Definition: iCubHand.h:61
yarp::sig::Matrix analog_bounds_
Definition: iCubHand.h:89
yarp::os::BufferedPort< yarp::os::Bottle > port_analogs_
Definition: iCubHand.h:75