ANNarchy iCub Interface 1.1.1
Loading...
Searching...
No Matches
JointPopulation.py
1"""
2 Copyright (C) 2021-2022 Torsten Fietzek; Helge Ülo Dinkelbach
3
4 JointPopulation.py is part of the ANNarchy iCub interface
5
6 This program is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 The ANNarchy iCub interface is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this headers. If not, see [http://www.gnu.org/licenses/].
18 """
19
20import ANN_iCub_Interface
21from ANNarchy.core.Neuron import Neuron
22try:
23 from ANNarchy.intern.SpecificPopulation import SpecificPopulation
24 from ANNarchy.intern.Messages import _error
25
26except:
27 from ANNarchy.core.SpecificPopulation import SpecificPopulation
28 from ANNarchy.core.Global import _error
29
30
31class JointControl(SpecificPopulation):
32 """
33 ANNarchy population class to connect with the iCub joint control, e. g. arm or head.
34 Readout the angles from the ANNarchy Population and send it to the iCub.
35 """
36
37 def __init__(self, geometry=None, neuron=Neuron(equations="r = 0.0"), ip_address="0.0.0.0", port=50010, copied=False, name=None):
38 """Init the JointControl population.
39
40 Args:
41 geometry (tuple, optional): ANNarchy population geometry. Defaults to None.
42 neuron (Neuron, optional): ANNarchy Neuron, being used in the population. Defaults to Neuron(equations="r = 0.0").
43 ip_address (str, optional): ip-address of the gRPC connection. Need to fit with the respective joint writer module. Defaults to "0.0.0.0".
44 port (int, optional): port of the gRPC connection. Need to fit with the respective joint reader module. Defaults to 50010.
45 copied (bool, optional): ANNarchy specific parameter. Defaults to False.
46 name (str, optional): individiual name for the population. Defaults to None.
47 """
48 SpecificPopulation.__init__(self, geometry=geometry, neuron=neuron, copied=copied, name=name)
49
50 self._ip_address = ip_address
51 self._port = port
52
54
55 SpecificPopulation._init_attributes(self)
56
57 self.cyInstance.set_ip_address(self._ip_address)
58 self.cyInstance.set_port(self._port)
59
60 def _copy(self):
61
62 return JointControl(geometry=self.geometry, neuron=self.neuron_type, ip_address=self._ip_address, port=self._port, copied=True, name=self.name)
63
64 @property
65 def ip_address(self):
66 if self.initialized:
67 return self.cyInstance.get_ip_address()
68 else:
69 _error("Read-out IP address is only valid after compile().")
70
71 @ip_address.setter
72 def ip_address(self, value):
73 if self.initialized:
74 self.cyInstance.set_ip_address(value)
75 else:
76 _error("Changing IP address is only valid after compile() or constructor.")
77
78 @property
79 def port(self):
80 if self.initialized:
81 return self.cyInstance.get_port()
82 else:
83 _error("Read-out port is only valid after compile().")
84
85 @port.setter
86 def port(self, value):
87 if self.initialized:
88 self.cyInstance.set_port(value)
89 else:
90 _error("Changing port is only valid after compile() or constructor.")
91
92 def _generate(self):
93 """
94 read out code for iCub through gRPC
95 """
96 include_paths = ANN_iCub_Interface.__path__[0]+"/grpc/"
97
98 self._specific_template['include_additional'] = """// grpc stuff
99#include "ANN_iCub_Interface/grpc/WriteOutputServer.h"
100"""
101
102 self._specific_template['declare_additional'] = """
103 std::string ip_address;
104 unsigned int port;
105 WriteOutputServerInstance<PopStruct%(id)s>* joint_server=nullptr;
106 std::thread server_thread;
107
108 ~PopStruct%(id)s() {
109 if (joint_server != nullptr) {
110 joint_server->shutdown();
111 server_thread.join();
112 }
113 }
114 """ % {'id': self.id}
115 self._specific_template['access_additional'] = """
116 // Joint Source ip address
117 void set_ip_address(std::string value) {
118 ip_address = value;
119 }
120 std::string get_ip_address() {
121 return ip_address;
122 }
123
124 // Joint Source port
125 void set_port(unsigned int value) {
126 port = value;
127 }
128 unsigned int get_port() {
129 return port;
130 }
131
132 void connect() {
133 if (joint_server == nullptr) {
134 joint_server = new WriteOutputServerInstance<PopStruct%(id)s>(ip_address, port, new WriteOutputServiceImpl<PopStruct%(id)s>(this) );
135 this->server_thread = std::thread(&WriteOutputServerInstance<PopStruct%(id)s>::wait, this->joint_server);
136 } else {
137 std::cerr << "Population %(name)s already connected" << std::endl;
138 }
139 }
140 """ % {'id': self.id, 'name': self.name}
141 self._specific_template['export_additional'] = """
142 # IP Address and port
143 void set_ip_address(string)
144 string get_ip_address()
145 void set_port(unsigned int)
146 unsigned int get_port()
147 void connect()
148"""
149 self._specific_template['wrapper_access_additional'] = """
150 # IP Address and port
151 def set_ip_address(self, value):
152 pop%(id)s.set_ip_address(value.encode('utf-8'))
153 def get_ip_address(self):
154 return pop%(id)s.get_ip_address()
155 def set_port(self, value):
156 pop%(id)s.set_port(value)
157 def get_port(self):
158 return pop%(id)s.get_port()
159 def connect(self):
160 pop%(id)s.connect()
161""" %{'id': self.id}
162
163 def _instantiate(self, cython_module):
164 # initializes cython wrapper
165 SpecificPopulation._instantiate(self, cython_module)
166
167 def connect(self):
168 """Connect the population to the gRPC socket. Need to be called once after compile."""
169 # create socket and connect
170 if self.initialized:
171 self.cyInstance.connect()
172
173
174class JointReadout(SpecificPopulation):
175 """
176 ANNarchy population class to connect with the iCub joint readout, e. g. arm or head.
177 Readout the angles from the iCub and set it as population activation.
178 """
179
180 def __init__(self, geometry=None, joints=None, encoded=False, ip_address="0.0.0.0", port=50005, copied=False, name=None):
181 """Init the JointReadout population.
182
183 Args:
184 geometry (tuple, optional): ANNarchy population geometry. Defaults to None.
185 joints (list, optional): Specify the joints, which should be accessed. Defaults to None.
186 encoded (bool, optional): Specify if the joint angles should be encoded with a population coding. Defaults to False.
187 ip_address (str, optional): ip-address of the gRPC connection. Need to fit with the respective joint reader module. Defaults to "0.0.0.0".
188 port (int, optional): port of the gRPC connection. Need to fit with the respective joint reader module. Defaults to 50005.
189 copied (bool, optional): ANNarchy specific parameter. Defaults to False.
190 name (str, optional): individiual name for the population. Defaults to None.
191 """
192 SpecificPopulation.__init__(self, geometry=geometry, neuron=Neuron(equations="r = 0.0"), copied=copied, name=name)
193
194 self._ip_address = ip_address
195 self._port = port
196 self._joints = joints
197 self._encoded = encoded
198
200 SpecificPopulation._init_attributes(self)
201
202 self.cyInstance.set_joints(self._joints)
203 self.cyInstance.set_encoded(self._encoded)
204 self.cyInstance.set_ip_address(self._ip_address)
205 self.cyInstance.set_port(self._port)
206
207 def _copy(self):
208 return JointReadout(geometry=self.geometry, joints=self._joints, encoded=self._encoded, ip_address=self._ip_address, port=self._port, copied=True, name=self.name)
209
210 @property
211 def ip_address(self):
212 if self.initialized:
213 return self.cyInstance.get_ip_address()
214 else:
215 _error("Read-out IP address is only valid after compile().")
216
217 @ip_address.setter
218 def ip_address(self, value):
219 if self.initialized:
220 self.cyInstance.set_ip_address(value)
221 else:
222 _error("Changing IP address is only valid after compile() or constructor.")
223
224 @property
225 def port(self):
226 if self.initialized:
227 return self.cyInstance.get_port()
228 else:
229 _error("Read-out port is only valid after compile().")
230
231 @port.setter
232 def port(self, value):
233 if self.initialized:
234 self.cyInstance.set_port(value)
235 else:
236 _error("Changing port is only valid after compile() or constructor.")
237
238 @property
239 def joints(self):
240 if self.initialized:
241 return self.cyInstance.get_joints()
242 else:
243 _error("Read-out joints is only valid after compile().")
244
245 @joints.setter
246 def joints(self, value):
247 if self.initialized:
248 self.cyInstance.set_joints(value)
249 else:
250 _error("Changing joints is only valid after compile() or constructor.")
251
252 @property
253 def encoded(self):
254 if self.initialized:
255 return self.cyInstance.get_encoded()
256 else:
257 _error("Read-out encoded is only valid after compile().")
258
259 @encoded.setter
260 def encoded(self, value):
261 if self.initialized:
262 self.cyInstance.set_encoded(value)
263 else:
264 _error("Changing encoded is only valid after compile() or constructor.")
265
266 def _generate(self):
267 """
268 read out code for iCub through gRPC
269 """
270 include_paths = ANN_iCub_Interface.__path__[0]+"/grpc/"
271
272 self._specific_template['include_additional'] = """// grpc stuff
273#include "ANN_iCub_Interface/grpc/ProvideInputClient.h"
274"""
275 self._specific_template['declare_additional'] = """
276 std::string ip_address;
277 unsigned int port;
278 ClientInstance* joint_source=nullptr;
279 std::vector<int> joints;
280 bool encoded;
281 """
282 self._specific_template['access_additional'] = """
283 // Joint Source ip address
284 void set_ip_address(std::string value) {
285 ip_address = value;
286 }
287 std::string get_ip_address() {
288 return ip_address;
289 }
290
291 // Joint Source port
292 void set_port(unsigned int value) {
293 port = value;
294 }
295 unsigned int get_port() {
296 return port;
297 }
298
299 // Joint Source joint selection
300 void set_joints(std::vector<int> value) {
301 joints = value;
302 }
303 std::vector<int> get_joints() {
304 return joints;
305 }
306
307 // Joint Source joint encoding
308 void set_encoded(bool value) {
309 encoded = value;
310 }
311 bool get_encoded() {
312 return encoded;
313 }
314
315 void connect() {
316 if (joint_source == nullptr) {
317 joint_source = new ClientInstance(ip_address, port);
318 } else {
319 std::cerr << "Population %(name)s already connected" << std::endl;
320 }
321 }
322 """ % {'name': self.name}
323 self._specific_template['export_additional'] = """
324 # IP Address and port
325 void set_ip_address(string)
326 string get_ip_address()
327 void set_port(unsigned int)
328 unsigned int get_port()
329 void set_joints(vector[int])
330 vector[int] get_joints()
331 void set_encoded(bool)
332 bool get_encoded()
333 void connect()
334"""
335 self._specific_template['wrapper_access_additional'] = """
336 # IP Address and port
337 def set_ip_address(self, value):
338 pop%(id)s.set_ip_address(value.encode('utf-8'))
339 def get_ip_address(self):
340 return pop%(id)s.get_ip_address()
341 def set_port(self, value):
342 pop%(id)s.set_port(value)
343 def get_port(self):
344 return pop%(id)s.get_port()
345 def set_joints(self, value):
346 pop%(id)s.set_joints(value)
347 def get_joints(self):
348 return pop%(id)s.get_joints()
349 def set_encoded(self, value):
350 pop%(id)s.set_encoded(value)
351 def get_encoded(self):
352 return pop%(id)s.get_encoded()
353 def connect(self):
354 pop%(id)s.connect()
355""" %{'id': self.id}
356
357 if len(self._joints) == 0:
358 self._specific_template['update_variables'] = """
359 #pragma omp single
360 {
361 r = joint_source->retrieve_alljoints(encoded);
362 }
363 """
364 elif len(self._joints) == 1:
365 self._specific_template['update_variables'] = """
366 #pragma omp single
367 {
368 r = joint_source->retrieve_singlejoint(joints[0], encoded);
369 }
370 """
371 else:
372 self._specific_template['update_variables'] = """
373 #pragma omp single
374 {
375 r = joint_source->retrieve_multijoints(joints, encoded);
376 }
377 """
378
379 def _instantiate(self, cython_module):
380 # initializes cython wrapper
381 SpecificPopulation._instantiate(self, cython_module)
382
383 def connect(self):
384 """Connect the population to the gRPC socket. Need to be called once after compile."""
385 # create socket and connect
386 if self.initialized:
387 self.cyInstance.connect()
__init__(self, geometry=None, neuron=Neuron(equations="r = 0.0"), ip_address="0.0.0.0", port=50010, copied=False, name=None)
__init__(self, geometry=None, joints=None, encoded=False, ip_address="0.0.0.0", port=50005, copied=False, name=None)