marxbotsensors.cpp
1 /********************************************************************************
2  * FARSA Experiments Library *
3  * Copyright (C) 2007-2012 *
4  * Gianluca Massera <emmegian@yahoo.it> *
5  * Stefano Nolfi <stefano.nolfi@istc.cnr.it> *
6  * Tomassino Ferrauto <tomassino.ferrauto@istc.cnr.it> *
7  * Onofrio Gigliotta <onofrio.gigliotta@istc.cnr.it> *
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  * This program is distributed in the hope that it will be useful, *
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
17  * GNU General Public License for more details. *
18  * *
19  * You should have received a copy of the GNU General Public License *
20  * along with this program; if not, write to the Free Software *
21  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *
22  ********************************************************************************/
23 
24 #include "marxbotsensors.h"
25 #include "configurationhelper.h"
26 #include "logger.h"
27 #include "graphicalwobject.h"
28 #include "arena.h"
29 #include "mathutils.h"
30 #include "utilitiesexceptions.h"
31 #include <QMutex>
32 #include <limits>
33 
34 namespace farsa {
35 
37  Sensor(params, prefix),
38  m_marxbotResource("robot"),
39  m_neuronsIteratorResource("neuronsIterator")
40 {
41  // Reading parameters
44 
45  // Declaring the resources that are needed here
47 }
48 
50 {
51  // Nothing to do here
52 }
53 
54 void MarXbotSensor::save(ConfigurationParameters& params, QString prefix)
55 {
56  // Calling parent function
57  Sensor::save(params, prefix);
58 
59  // Saving parameters
60  params.startObjectParameters(prefix, "MarXbotSensor", this);
61  params.createParameter(prefix, "marxbot", m_marxbotResource);
62  params.createParameter(prefix, "neuronsIterator", m_neuronsIteratorResource);
63 }
64 
65 void MarXbotSensor::describe(QString type)
66 {
67  // Calling parent function
68  Sensor::describe(type);
69 
70  // Describing our parameters
71  Descriptor d = addTypeDescription(type, "The base class for MarXbot sensors");
72  d.describeString("marxbot").def("robot").help("The name of the resource associated with the MarXbot robot to use (default is \"robot\")");
73  d.describeString("neuronsIterator").def("neuronsIterator").help("The name of the resource associated with the neural network iterator (default is \"neuronsIterator\")");
74 }
75 
76 void MarXbotSensor::resourceChanged(QString resourceName, ResourceChangeType changeType)
77 {
78  // Calling parent function
79  Sensor::resourceChanged(resourceName, changeType);
80 
81  // Here we only check whether the resource has been deleted and reset the check flag, the
82  // actual work is done in subclasses
83  if (changeType == Deleted) {
85  return;
86  }
87 }
88 
90  MarXbotSensor(params, prefix),
91  m_robot(NULL),
92  m_neuronsIterator(NULL),
93  m_activeSensors(ConfigurationHelper::getBoolVector(params, prefix + "activeSensors", "111111111111111111111111")),
94  m_numActiveSensors(m_activeSensors.count(true))
95 {
96  if (m_activeSensors.size() != 24) {
97  ConfigurationHelper::throwUserConfigError(prefix + "activeSensors", params.getValue(prefix + "activeSensors"), "The parameter must be a list of exactly 24 elements either equal to 1 or to 0 (do not use any space to separate elements, just put them directly one after the other)");
98  }
99 }
100 
102 {
103  // Nothing to do here
104 }
105 
107 {
108  // Calling parent function
109  MarXbotSensor::save(params, prefix);
110 
111  // Saving parameters
112  params.startObjectParameters(prefix, "MarXbotProximityIRSensor", this);
113  QString activeSensorsString;
114  for (int i = 0; i < m_activeSensors.size(); i++) {
115  activeSensorsString += (m_activeSensors[i] ? "1" : "0");
116  }
117  params.createParameter(prefix, "activeSensors", activeSensorsString);
118 }
119 
121 {
122  // Calling parent function
124 
125  // Describing our parameters
126  Descriptor d = addTypeDescription(type, "The infrared proximity sensors of the MarXbot robot", "The infrared proximity sensors of the MarXbot robot. These are the very short range IR sensors all around the base");
127  d.describeString("activeSensors").def("111111111111111111111111").help("Which IR sensors of the robot are actually enabled", "This is a string of exactly 24 elements. Each element can be either \"0\" or \"1\" to respectively disable/enable the corresponding proximity IR sensor. The first sensor is the one on the left side of the robot and the others follow counterclockwise (i.e. left, back, right, front)");
128 }
129 
131 {
132  // Checking all resources we need exist
134 
135  // Acquiring the lock to get resources
136  ResourcesLocker locker( this );
137 
138  m_neuronsIterator->setCurrentBlock(name());
139  for (int i = 0; i < m_activeSensors.size(); i++) {
140  if (m_activeSensors[i]) {
141  m_neuronsIterator->setInput(applyNoise(m_robot->proximityIRSensorController()->activation(i), 0.0, 1.0));
142  m_neuronsIterator->nextNeuron();
143  }
144  }
145 }
146 
148 {
149  return m_numActiveSensors;
150 }
151 
152 void MarXbotProximityIRSensor::resourceChanged(QString resourceName, ResourceChangeType changeType)
153 {
154  // Calling parent function
155  MarXbotSensor::resourceChanged(resourceName, changeType);
156 
157  if (changeType == Deleted) {
158  return;
159  }
160 
161  if (resourceName == m_marxbotResource) {
162  m_robot = getResource<PhyMarXbot>();
163 
164  // Eanbling sensors
165  m_robot->proximityIRSensorController()->setEnabled(true);
166 
167  // Now enabling/disabling individual sensors depending on the m_activeSensors vector
168  for (int i = 0; i < m_activeSensors.size(); i++) {
169  m_robot->proximityIRSensorController()->setSensorActive(i, m_activeSensors[i]);
170  }
171  } else if (resourceName == m_neuronsIteratorResource) {
172  m_neuronsIterator = getResource<NeuronsIterator>();
173  m_neuronsIterator->setCurrentBlock(name());
174 
175  // We use the actual sensor ID in the neuron name
176  for (int i = 0; i < m_activeSensors.size(); i++) {
177  if (m_activeSensors[i]) {
178  m_neuronsIterator->setGraphicProperties("ir" + QString::number(i), 0.0, 1.0, Qt::red);
179  m_neuronsIterator->nextNeuron();
180  }
181  }
182  } else {
183  Logger::info("Unknown resource " + resourceName + " for " + name());
184  }
185 }
186 
188  MarXbotSensor(params, prefix),
189  m_robot(NULL),
190  m_neuronsIterator(NULL),
191  m_arena(NULL),
192  m_invertActivation(ConfigurationHelper::getBool(params, prefix + "invertActivation", false))
193 {
194  // Here we also need the arena to work
195  addUsableResource("arena");
196 }
197 
199 {
200  // Nothing to do here
201 }
202 
204 {
205  // Calling parent function
206  MarXbotSensor::save(params, prefix);
207 
208  // Saving parameters
209  params.startObjectParameters(prefix, "MarXbotGroundBottomIRSensor", this);
210  params.createParameter(prefix, "invertActivation", (m_invertActivation ? "true" : "false"));
211 }
212 
214 {
215  // Calling parent function
217 
218  // Describing our parameters
219  Descriptor d = addTypeDescription(type, "The infrared ground bottom sensors of the MarXbot robot", "The infrared ground bottom sensors of the MarXbot robot. These are the four ground sensors below the robot battery pack.");
220  d.describeBool("invertActivation").def(false).help("If true inverts the activation of the sensors", "If true the sensor is activated with 0.0 above white and with 1.0 above black, if false the opposite holds. The default value is false");
221 }
222 
224 {
225  // Checking all resources we need exist
227 
228  // Acquiring the lock to get resources
229  ResourcesLocker locker( this );
230 
231  // Setting neurons activations
232  m_neuronsIterator->setCurrentBlock(name());
233  for (int i = 0; i < size(); i++, m_neuronsIterator->nextNeuron()) {
234  const wVector sensorPosition = m_robot->matrix().transformVector(m_robot->groundBottomIRSensorController()->sensors()[i].getPosition());
235  const QColor color = getColorAtArenaGroundPosition(m_arena, sensorPosition);
236  const real actv = real(qGray(color.rgb())) / 255.0;
237 
238  if (m_invertActivation) {
239  m_neuronsIterator->setInput(applyNoise(1.0 - actv, 0.0, 1.0));
240  } else {
241  m_neuronsIterator->setInput(applyNoise(actv, 0.0, 1.0));
242  }
243  }
244 }
245 
247 {
248  return 4;
249 }
250 
251 void MarXbotGroundBottomIRSensor::resourceChanged(QString resourceName, ResourceChangeType changeType)
252 {
253  // Calling parent function
254  MarXbotSensor::resourceChanged(resourceName, changeType);
255 
256  if (changeType == Deleted) {
257  return;
258  }
259 
260  if (resourceName == m_marxbotResource) {
261  m_robot = getResource<PhyMarXbot>();
262 
263  // Eanbling sensors
264  m_robot->groundBottomIRSensorController()->setEnabled(true);
265  } else if (resourceName == m_neuronsIteratorResource) {
266  m_neuronsIterator = getResource<NeuronsIterator>();
267  m_neuronsIterator->setCurrentBlock(name());
268  for (int i = 0; i < size(); i++, m_neuronsIterator->nextNeuron()) {
269  m_neuronsIterator->setGraphicProperties("gb" + QString::number(i), 0.0, 1.0, Qt::red);
270  }
271  } else if (resourceName == "arena") {
272  // Storing the pointer to the arena
273  m_arena = getResource<Arena>();
274  } else {
275  Logger::info("Unknown resource " + resourceName + " for " + name());
276  }
277 }
278 
280  MarXbotSensor(params, prefix),
281  m_robot(NULL),
282  m_neuronsIterator(NULL),
283  m_arena(NULL)
284 {
285  // Here we also need the arena to work
286  addUsableResource("arena");
287 }
288 
290 {
291  // Nothing to do here
292 }
293 
295 {
296  // Calling parent function
297  MarXbotSensor::save(params, prefix);
298 
299  // Saving parameters
300  params.startObjectParameters(prefix, "MarXbotGroundAroundIRSensor", this);
301 }
302 
304 {
305  // Calling parent function
307 
308  // Describing our parameters
309  Descriptor d = addTypeDescription(type, "The infrared ground around sensors of the MarXbot robot", "The infrared ground around sensors of the MarXbot robot. These are the eight ground sensors below the base of the robot (just above the wheels).");
310 }
311 
313 {
314  // Checking all resources we need exist
316 
317  // Acquiring the lock to get resources
318  ResourcesLocker locker( this );
319 
320  // Setting neurons activations
321  m_neuronsIterator->setCurrentBlock(name());
322  for (int i = 0; i < size(); i++, m_neuronsIterator->nextNeuron()) {
323  const wVector sensorPosition = m_robot->matrix().transformVector(m_robot->groundAroundIRSensorController()->sensors()[i].getPosition());
324  const QColor color = getColorAtArenaGroundPosition(m_arena, sensorPosition);
325  const real actv = real(qGray(color.rgb())) / 255.0;
326 
327  m_neuronsIterator->setInput(applyNoise(actv, 0.0, 1.0));
328  }
329 }
330 
332 {
333  return 8;
334 }
335 
336 void MarXbotGroundAroundIRSensor::resourceChanged(QString resourceName, ResourceChangeType changeType)
337 {
338  // Calling parent function
339  MarXbotSensor::resourceChanged(resourceName, changeType);
340 
341  if (changeType == Deleted) {
342  return;
343  }
344 
345  if (resourceName == m_marxbotResource) {
346  m_robot = getResource<PhyMarXbot>();
347 
348  // Eanbling sensors
349  m_robot->groundAroundIRSensorController()->setEnabled(true);
350  } else if (resourceName == m_neuronsIteratorResource) {
351  m_neuronsIterator = getResource<NeuronsIterator>();
352  m_neuronsIterator->setCurrentBlock(name());
353  for (int i = 0; i < size(); i++, m_neuronsIterator->nextNeuron()) {
354  m_neuronsIterator->setGraphicProperties("ga" + QString::number(i), 0.0, 1.0, Qt::red);
355  }
356  } else if (resourceName == "arena") {
357  // Storing the pointer to the arena
358  m_arena = getResource<Arena>();
359  } else {
360  Logger::info("Unknown resource " + resourceName + " for " + name());
361  }
362 }
363 
365  MarXbotSensor(params, prefix),
366  m_robot(NULL),
367  m_neuronsIterator(NULL),
368  m_numReceptors(ConfigurationHelper::getInt(params, prefix + "numReceptors", 8)),
369  m_useRedChannel(ConfigurationHelper::getBool(params, prefix + "useRedChannel", true)),
370  m_useGreenChannel(ConfigurationHelper::getBool(params, prefix + "useGreenChannel", true)),
371  m_useBlueChannel(ConfigurationHelper::getBool(params, prefix + "useBlueChannel", true)),
372  m_usedColorChannels((m_useRedChannel ? 1 : 0) + (m_useGreenChannel ? 1 : 0) + (m_useBlueChannel ? 1 : 0)),
373  m_aperture(ConfigurationHelper::getDouble(params, prefix + "aperture", 360.0f)),
374  m_maxDistance(ConfigurationHelper::getDouble(params, prefix + "maxDistance", +Infinity)),
375  m_camera(NULL),
376  m_drawCamera(ConfigurationHelper::getBool(params, prefix + "drawCamera", true))
377 {
378  // Few sanity checks
379  if (m_numReceptors <= 0) {
380  ConfigurationHelper::throwUserConfigError(prefix + "numReceptors", params.getValue(prefix + "numReceptors"), "The parameter must be an integer greater or equal to 1");
381  }
382  if ((m_aperture < 0.0f) || (m_aperture > 360.0f)) {
383  ConfigurationHelper::throwUserConfigError(prefix + "aperture", params.getValue(prefix + "aperture"), "The parameter must be a real number between 0 and 360");
384  }
385 }
386 
388 {
389  // Deleting the camera
390  delete m_camera;
391 }
392 
394 {
395  // Calling parent function
396  MarXbotSensor::save(params, prefix);
397 
398  // Saving parameters
399  params.startObjectParameters(prefix, "MarXbotLinearCameraSensor", this);
400  params.createParameter(prefix, "numReceptors", QString::number(m_numReceptors));
401  params.createParameter(prefix, "useRedChannel", (m_useRedChannel ? "true" : "false"));
402  params.createParameter(prefix, "useGreenChannel", (m_useGreenChannel ? "true" : "false"));
403  params.createParameter(prefix, "useBlueChannel", (m_useBlueChannel ? "true" : "false"));
404  params.createParameter(prefix, "aperture", QString::number(m_aperture));
405  params.createParameter(prefix, "maxDistance", QString::number(m_maxDistance));
406  params.createParameter(prefix, "drawCamera", (m_drawCamera ? "true" : "false"));
407 }
408 
410 {
411  // Calling parent function
413 
414  // Describing our parameters
415  Descriptor d = addTypeDescription(type, "The linear camera sensor of the MarXbot robot", "This is a 360° linear camera");
416  d.describeInt("numReceptors").def(8).limits(1, MaxInteger).help("The number of receptors of the sensor", "Each receptor returns three values, one for each of the three colors (red, green, blue). This means that the size returned by this sensor is 3 * numReceptors (default is 8)");
417  d.describeBool("useRedChannel").def(true).help("Whether the red component of the perceived objects should be used or not (default true)");
418  d.describeBool("useGreenChannel").def(true).help("Whether the green component of the perceived objects should be used or not (default true)");
419  d.describeBool("useBlueChannel").def(true).help("Whether the blue component of the perceived objects should be used or not (default true)");
420  d.describeReal("aperture").def(360.0f).limits(0.0f, 360.0f).help("The aperture of the camera in degrees", "The real MarXbot has an omnidirectional camera, so you can use here any value up to 360 degrees (default is 360)");
421  d.describeReal("maxDistance").def(+Infinity).limits(0.0f, +Infinity).help("The distance above which objects are not seen by the camera in meters");
422  d.describeBool("drawCamera").def(true).help("Whether to draw the camera or not");
423 }
424 
426 {
427  // Checking all resources we need exist
429 
430  // Acquiring the lock to get resources
431  ResourcesLocker locker(this);
432 
433  // Updating the camera
434  m_camera->update();
435 
436  // Reading activations: first the red one, then the green one and finally the blue one
437  m_neuronsIterator->setCurrentBlock(name());
438  if (m_useRedChannel) {
439  for (int i = 0; i < m_numReceptors; i++, m_neuronsIterator->nextNeuron()) {
440  m_neuronsIterator->setInput(applyNoise(m_camera->colorForReceptor(i).redF(), 0.0, 1.0));
441  }
442  }
443  if (m_useGreenChannel) {
444  for (int i = 0; i < m_numReceptors; i++, m_neuronsIterator->nextNeuron()) {
445  m_neuronsIterator->setInput(applyNoise(m_camera->colorForReceptor(i).greenF(), 0.0, 1.0));
446  }
447  }
448  if (m_useBlueChannel) {
449  for (int i = 0; i < m_numReceptors; i++, m_neuronsIterator->nextNeuron()) {
450  m_neuronsIterator->setInput(applyNoise(m_camera->colorForReceptor(i).blueF(), 0.0, 1.0));
451  }
452  }
453 }
454 
456 {
457  return m_numReceptors * m_usedColorChannels;
458 }
459 
460 void MarXbotLinearCameraSensor::resourceChanged(QString resourceName, ResourceChangeType changeType)
461 {
462  // Calling parent function
463  MarXbotSensor::resourceChanged(resourceName, changeType);
464 
465  if (changeType == Deleted) {
466  // Deleting the camera if the robot was deleted
467  if (resourceName == m_marxbotResource) {
468  delete m_camera;
469  m_camera = NULL;
470  }
471 
472  return;
473  }
474 
475  if (resourceName == m_marxbotResource) {
476  m_robot = getResource<PhyMarXbot>();
477 
478  // Now we can also create the camera
479  wMatrix mtr = wMatrix::roll(-PI_GRECO / 2.0);
480 #if defined(__GNUC__) && defined(DEVELOPER_WARNINGS)
481  #warning QUI INVECE DI UNA COSTANTE, CALCOLARSI UNA POSIZIONE DALLE DIMENSIONI DEL ROBOT
482 #endif
483  mtr.w_pos.z = 0.13f;
484  m_camera = new LinearCamera(m_robot, mtr, toRad(m_aperture), m_numReceptors, m_maxDistance, Qt::black);
485 
486  // Sharing resources with the camera
487  m_camera->shareResourcesWith(this);
488  m_camera->drawCamera(m_drawCamera);
489  } else if (resourceName == m_neuronsIteratorResource) {
490  m_neuronsIterator = getResource<NeuronsIterator>();
491  m_neuronsIterator->setCurrentBlock(name());
492  if (m_useRedChannel) {
493  for (int i = 0; i < m_numReceptors; i++, m_neuronsIterator->nextNeuron()) {
494  m_neuronsIterator->setGraphicProperties("lr" + QString::number(i), 0.0, 1.0, Qt::red);
495  }
496  }
497  if (m_useGreenChannel) {
498  for (int i = 0; i < m_numReceptors; i++, m_neuronsIterator->nextNeuron()) {
499  m_neuronsIterator->setGraphicProperties("lg" + QString::number(i), 0.0, 1.0, Qt::red);
500  }
501  }
502  if (m_useBlueChannel) {
503  for (int i = 0; i < m_numReceptors; i++, m_neuronsIterator->nextNeuron()) {
504  m_neuronsIterator->setGraphicProperties("lb" + QString::number(i), 0.0, 1.0, Qt::red);
505  }
506  }
507  } else {
508  Logger::info("Unknown resource " + resourceName + " for " + name());
509  }
510 }
511 
513  MarXbotSensor(params, prefix),
514  m_robot(NULL),
515  m_neuronsIterator(NULL),
516  m_numReceptors(ConfigurationHelper::getInt(params, prefix + "numReceptors", 8)),
517  m_useRedChannel(ConfigurationHelper::getBool(params, prefix + "useRedChannel", true)),
518  m_useGreenChannel(ConfigurationHelper::getBool(params, prefix + "useGreenChannel", true)),
519  m_useBlueChannel(ConfigurationHelper::getBool(params, prefix + "useBlueChannel", true)),
520  m_usedColorChannels((m_useRedChannel ? 1 : 0) + (m_useGreenChannel ? 1 : 0) + (m_useBlueChannel ? 1 : 0)),
521  m_aperture(ConfigurationHelper::getDouble(params, prefix + "aperture", 360.0f)),
522  m_maxDistance(ConfigurationHelper::getDouble(params, prefix + "maxDistance", +Infinity)),
523  m_receptorsRanges(),
524  m_camera(NULL),
525  m_drawCamera(ConfigurationHelper::getBool(params, prefix + "drawCamera", true))
526 {
527  // We have to get here the receptorsRanges parameter
528  QString receptorsRangesStr = params.getValue(prefix + "receptorsRanges");
529  if (receptorsRangesStr.isEmpty()) {
530  // Here we use aperture and numReceptors, doing few sanity checks
531  if (m_numReceptors <= 0) {
532  ConfigurationHelper::throwUserConfigError(prefix + "numReceptors", params.getValue(prefix + "numReceptors"), "The parameter must be an integer greater or equal to 1");
533  }
534  if ((m_aperture < 0.0f) || (m_aperture > 360.0f)) {
535  ConfigurationHelper::throwUserConfigError(prefix + "aperture", params.getValue(prefix + "aperture"), "The parameter must be a real number between 0 and 360");
536  }
537  } else {
538  // Here we use receptorsRanges, checking that neither aperture nor numReceptors is set
539  if (!params.getValue(prefix + "numReceptors").isEmpty() || !params.getValue(prefix + "aperture").isEmpty()) {
540  ConfigurationHelper::throwUserConfigError(prefix + "receptorsRanges", params.getValue(prefix + "receptorsRanges"), "You must not specify the receptorsRanges parameter if either aperture or numReceptors has been specified");
541  }
542 
543  // Now getting the parameter
544  bool ok;
545  m_receptorsRanges = SimpleInterval::vectorOfSimpleIntervalsFromString(receptorsRangesStr, &ok);
546  if (!ok) {
547  ConfigurationHelper::throwUserConfigError(prefix + "receptorsRanges", params.getValue(prefix + "receptorsRanges"), "The receptorsRanges parameter must be a comma separated list of simple intervals");
548  }
549 
550  // We also have to convert angles to radiants
551  for (int i = 0; i < m_receptorsRanges.size(); i++) {
552  m_receptorsRanges[i].start = toRad(m_receptorsRanges[i].start);
553  m_receptorsRanges[i].end = toRad(m_receptorsRanges[i].end);
554  }
555 
556  // Setting m_numReceptors to the correct value
557  m_numReceptors = m_receptorsRanges.size();
558  }
559 }
560 
562 {
563  // Deleting the camera
564  delete m_camera;
565 }
566 
568 {
569  // Calling parent function
570  MarXbotSensor::save(params, prefix);
571 
572  // Saving parameters
573  params.startObjectParameters(prefix, "MarXbotLinearCameraSensorNew", this);
574  params.createParameter(prefix, "numReceptors", QString::number(m_numReceptors));
575  params.createParameter(prefix, "aperture", QString::number(m_aperture));
576  params.createParameter(prefix, "maxDistance", QString::number(m_maxDistance));
577  params.createParameter(prefix, "useRedChannel", (m_useRedChannel ? "true" : "false"));
578  params.createParameter(prefix, "useGreenChannel", (m_useGreenChannel ? "true" : "false"));
579  params.createParameter(prefix, "useBlueChannel", (m_useBlueChannel ? "true" : "false"));
580  params.createParameter(prefix, "drawCamera", (m_drawCamera ? "true" : "false"));
581 }
582 
584 {
585  // Calling parent function
587 
588  // Describing our parameters
589  Descriptor d = addTypeDescription(type, "The linear camera sensor of the MarXbot robot (new implementation)", "This is a 360° linear camera");
590  d.describeInt("numReceptors").def(8).limits(1, MaxInteger).help("The number of receptors of the sensor", "Each receptor returns three values, one for each of the three colors (red, green, blue). This means that the size returned by this sensor is 3 * numReceptors (default is 8)");
591  d.describeReal("aperture").def(360.0f).limits(0.0f, 360.0f).help("The aperture of the camera in degrees", "The real MarXbot has an omnidirectional camera, so you can use here any value up to 360 degrees (default is 360)");
592  d.describeReal("maxDistance").def(+Infinity).limits(0.0f, +Infinity).help("The distance above which objects are not seen by the camera in meters");
593  d.describeString("receptorsRanges").def("").help("The range for each receptor", "This parameter is a comma separated list of ranges (in the form [start, end]), each range being the aperture of a single receptor. The number of receptors is equal to the number of ranges. The start and end angles of the range are in degrees. Note that if you specify this parameter you must not specify the aperture neither the numReceptors parameters.");
594  d.describeBool("useRedChannel").def(true).help("Whether the red component of the perceived objects should be used or not (default true)");
595  d.describeBool("useGreenChannel").def(true).help("Whether the green component of the perceived objects should be used or not (default true)");
596  d.describeBool("useBlueChannel").def(true).help("Whether the blue component of the perceived objects should be used or not (default true)");
597  d.describeBool("drawCamera").def(true).help("Whether to draw the camera or not");
598 }
599 
601 {
602  // Checking all resources we need exist
604 
605  // Acquiring the lock to get resources
606  ResourcesLocker locker(this);
607 
608  // Updating the camera
609  m_camera->update();
610 
611  // Reading activations: first the red one, then the green one and finally the blue one
612  m_neuronsIterator->setCurrentBlock(name());
613  if (m_useRedChannel) {
614  for (int i = 0; i < m_numReceptors; i++, m_neuronsIterator->nextNeuron()) {
615  m_neuronsIterator->setInput(applyNoise(m_camera->colorForReceptor(i).redF(), 0.0, 1.0));
616  }
617  }
618  if (m_useGreenChannel) {
619  for (int i = 0; i < m_numReceptors; i++, m_neuronsIterator->nextNeuron()) {
620  m_neuronsIterator->setInput(applyNoise(m_camera->colorForReceptor(i).greenF(), 0.0, 1.0));
621  }
622  }
623  if (m_useBlueChannel) {
624  for (int i = 0; i < m_numReceptors; i++, m_neuronsIterator->nextNeuron()) {
625  m_neuronsIterator->setInput(applyNoise(m_camera->colorForReceptor(i).blueF(), 0.0, 1.0));
626  }
627  }
628 }
629 
631 {
632  return m_numReceptors * m_usedColorChannels;
633 }
634 
635 void MarXbotLinearCameraSensorNew::resourceChanged(QString resourceName, ResourceChangeType changeType)
636 {
637  // Calling parent function
638  MarXbotSensor::resourceChanged(resourceName, changeType);
639 
640  if (changeType == Deleted) {
641  // Deleting the camera if the robot was deleted
642  if (resourceName == m_marxbotResource) {
643  delete m_camera;
644  m_camera = NULL;
645  }
646 
647  return;
648  }
649 
650  if (resourceName == m_marxbotResource) {
651  m_robot = getResource<PhyMarXbot>();
652 
653  // Now we can also create the camera
654  wMatrix mtr = wMatrix::roll(-PI_GRECO / 2.0);
655 #if defined(__GNUC__) && defined(DEVELOPER_WARNINGS)
656  #warning QUI INVECE DI UNA COSTANTE, CALCOLARSI UNA POSIZIONE DALLE DIMENSIONI DEL ROBOT
657 #endif
658  mtr.w_pos.z = 0.13f;
659  if (m_receptorsRanges.isEmpty()) {
660  m_camera = new LinearCameraNew::LinearCamera(m_robot, mtr, toRad(m_aperture), m_numReceptors, m_maxDistance, Qt::black);
661  } else {
662  m_camera = new LinearCameraNew::LinearCamera(m_robot, mtr, m_receptorsRanges, m_maxDistance, Qt::black);
663  }
664 
665  // Sharing resources with the camera
666  m_camera->shareResourcesWith(this);
667  m_camera->drawCamera(m_drawCamera);
668  } else if (resourceName == m_neuronsIteratorResource) {
669  m_neuronsIterator = getResource<NeuronsIterator>();
670  m_neuronsIterator->setCurrentBlock(name());
671  if (m_useRedChannel) {
672  for (int i = 0; i < m_numReceptors; i++, m_neuronsIterator->nextNeuron()) {
673  m_neuronsIterator->setGraphicProperties("lr" + QString::number(i), 0.0, 1.0, Qt::red);
674  }
675  }
676  if (m_useGreenChannel) {
677  for (int i = 0; i < m_numReceptors; i++, m_neuronsIterator->nextNeuron()) {
678  m_neuronsIterator->setGraphicProperties("lg" + QString::number(i), 0.0, 1.0, Qt::red);
679  }
680  }
681  if (m_useBlueChannel) {
682  for (int i = 0; i < m_numReceptors; i++, m_neuronsIterator->nextNeuron()) {
683  m_neuronsIterator->setGraphicProperties("lb" + QString::number(i), 0.0, 1.0, Qt::red);
684  }
685  }
686  } else {
687  Logger::info("Unknown resource " + resourceName + " for " + name());
688  }
689 }
690 
691 namespace __MarXbotTractionSensor_internal {
692  #ifndef GLMultMatrix
693  #define GLMultMatrix glMultMatrixf
694  // for double glMultMatrixd
695  #endif
696 
704  {
705  public:
730  TractionSensorGraphic(WObject *object, const wVector& offset, real radius, real scale = 1.0, real maxLength = 1.0, real minLength = 0.0, QString name = "unamed") :
731  GraphicalWObject(object->world(), name),
732  m_object(object),
733  m_radius(radius),
734  m_scale(scale),
735  m_maxLength(maxLength),
736  m_minLength(minLength),
738  m_vector(0.0, 0.0, 0.0),
739  m_vectorMutex()
740  {
741  // Attaching to object (which also becomes our owner). We also build the displacement matrix
742  wMatrix displacement = wMatrix::identity();
743  displacement.w_pos = offset;
744  attachToObject(m_object, true, displacement);
745 
746  // We also use our own color and texture
748  setTexture("");
749  }
750 
755  {
756  }
757 
766  void setVector(const wVector vector)
767  {
768  m_vectorMutex.lock();
769  m_vector = vector;
770  m_vectorMutex.unlock();
771  }
772 
773  protected:
782  virtual void render(RenderWObject* renderer, QGLContext* gw)
783  {
784  // Copying the m_activations vector to a local vector to avoid concurrent accesses.
785  m_vectorMutex.lock();
786  const wVector vector = m_vector;
787  m_vectorMutex.unlock();
788 
789  // Setting the matrix to draw the vector.
790  glPushMatrix();
791  GLMultMatrix(&tm[0][0]);
792 
793  bool xLimited;
794  bool yLimited;
795  const wVector vectorToDraw = wVector(limitComponent(vector.x, xLimited), limitComponent(vector.y, yLimited), vector.z).scale(m_scale);
796  const wVector xComponent(vectorToDraw.x, 0.0, vectorToDraw.z);
797  const wVector yComponent(0.0, vectorToDraw.y, vectorToDraw.z);
798 
799  // Drawing the three arrows (two for the axes, one for the resultant
800  drawArrow(xComponent, m_radius / 2.0, m_maxTipLength / 2.0, (xLimited ? Qt::red : Qt::cyan), renderer, gw);
801  drawArrow(yComponent, m_radius / 2.0, m_maxTipLength / 2.0, (yLimited ? Qt::red : Qt::cyan), renderer, gw);
802  drawArrow(vectorToDraw, m_radius, m_maxTipLength, Qt::cyan, renderer, gw);
803 
804  // Popping twice because we pushed both our matrix and the offset matrix
805  glPopMatrix();
806  glPopMatrix();
807  }
808 
823  void drawArrow(wVector vector, real radius, real maxTipLength, QColor col, RenderWObject* renderer, QGLContext* gw)
824  {
825  // Setting the color of the arrow
826  setColor(col);
827  renderer->container()->setupColorTexture(gw, renderer);
828 
829  const real vectorLength = vector.norm();
830  const wVector axis = vector.scale(1.0 / vectorLength);
831  const real bodyLength = vectorLength - maxTipLength;
832  const real tipLength = min(vectorLength, maxTipLength);
833  const real tipRadius = ((radius * 3.0) / 2.0) * (tipLength / maxTipLength);
834 
835  // First drawing the body if its length is positive
836  if (bodyLength > 0.0) {
837  RenderWObjectContainer::drawCylinder(axis, axis.scale(0.5 * bodyLength), bodyLength, radius, color());
838  }
839 
840  // Now drawing the tip as a cone:
841  {
842  GLUquadricObj *pObj;
843 
844  // opengl cylinder are aligned alogn the z axis, we want it along our axis,
845  // we create a rotation matrix to do the alignment. Moreover the cone must
846  // start at the end of the cylinder we draw before
847  const wVector tipDisplacement = (bodyLength < 0.0) ? wVector(0.0, 0.0, 0.0) : axis.scale(bodyLength);
848  glPushMatrix();
850  matrix.w_pos = tipDisplacement;
851  GLMultMatrix(&matrix[0][0]);
852 
853  // Get a new Quadric off the stack
854  pObj = gluNewQuadric();
855  gluQuadricTexture(pObj, true);
856  gluCylinder(pObj, tipRadius, 0, tipLength, 20, 2);
857 
858  // render the caps
859  gluQuadricOrientation(pObj, GLU_INSIDE);
860  gluDisk(pObj, 0.0f, tipRadius, 20, 1);
861 
862  gluDeleteQuadric(pObj);
863  glPopMatrix();
864  }
865  }
866 
876  real limitComponent(real v, bool& limited)
877  {
878  real l = fabs(v);
879  limited = false;
880  if (l < m_minLength) {
881  limited = true;
882  l = m_minLength;
883  } else if (l > m_maxLength) {
884  limited = true;
885  l = m_maxLength;
886  }
887  return (v < 0.0) ? -l : l;
888  }
889 
894 
899  const real m_radius;
900 
904  const real m_scale;
905 
914 
922 
929 
935  wVector m_vector;
936 
944  };
945 }
946 
947 using namespace __MarXbotTractionSensor_internal;
948 
950  MarXbotSensor(params, prefix),
951  m_robot(NULL),
952  m_neuronsIterator(NULL),
953  m_maxForce(ConfigurationHelper::getDouble(params, prefix + "maxForce", 1.0f)),
954  m_minForce(ConfigurationHelper::getDouble(params, prefix + "minForce", 0.0f)),
955  m_drawSensor(ConfigurationHelper::getBool(params, prefix + "drawSensor", true)),
956  m_graphics(NULL)
957 {
958  if (m_maxForce < 0.0) {
959  ConfigurationHelper::throwUserConfigError(prefix + "maxForce", params.getValue(prefix + "maxForce"), "The parameter must be a positive real number");
960  }
961  if (m_minForce < 0.0) {
962  ConfigurationHelper::throwUserConfigError(prefix + "minForce", params.getValue(prefix + "minForce"), "The parameter must be a positive real number");
963  }
964 }
965 
967 {
968  // Nothing to do here
969 }
970 
972 {
973  // Calling parent function
974  MarXbotSensor::save(params, prefix);
975 
976  // Saving parameters
977  params.startObjectParameters(prefix, "MarXbotTractionSensor", this);
978  params.createParameter(prefix, "maxForce", QString::number(m_maxForce));
979  params.createParameter(prefix, "minForce", QString::number(m_minForce));
980  params.createParameter(prefix, "drawSensor", m_drawSensor ? QString("true") : QString("false"));
981 }
982 
984 {
985  // Calling parent function
987 
988  // Describing our parameters
989  Descriptor d = addTypeDescription(type, "The traction sensors of the MarXbot robot", "The traction sensors of the MarXbot robot. It is placed between the base and the turret. Note that this sensor only works when the robot is in dynamic mode");
990  d.describeReal("maxForce").def(1.0f).limits(0.0f, +Infinity).help("The maximum possible value of the force", "This is the value of the force on one axis over which the corresponding neuron is activated with 1");
991  d.describeReal("minForce").def(0.0f).limits(0.0f, +Infinity).help("The minimum possible value of the force", "This is the value of the force on one axis under which the corresponding neuron is activated with 0");
992  d.describeBool("drawSensor").def(true).help("Whether to draw the sensor", "If true the sensor is graphically represented by an arrow in the direction of the current traction");
993 }
994 
996 {
997  // Checking all resources we need exist
999 
1000  // Acquiring the lock to get resources
1001  ResourcesLocker locker( this );
1002 
1003  m_neuronsIterator->setCurrentBlock(name());
1004  const wVector& t = m_robot->tractionSensorController()->traction();
1005 
1006  // The first two neurons correspond to the x axis, the second two to the y axis
1007  if (t.x > 0.0) {
1008  const real f = linearMap(t.x, m_minForce, m_maxForce, 0.0, 1.0);
1009  m_neuronsIterator->setInput(applyNoise(f, 0.0, 1.0));
1010  m_neuronsIterator->nextNeuron();
1011  m_neuronsIterator->setInput(0.0);
1012  m_neuronsIterator->nextNeuron();
1013  } else {
1014  const real f = linearMap(-t.x, m_minForce, m_maxForce, 0.0, 1.0);
1015  m_neuronsIterator->setInput(0.0);
1016  m_neuronsIterator->nextNeuron();
1017  m_neuronsIterator->setInput(applyNoise(f, 0.0, 1.0));
1018  m_neuronsIterator->nextNeuron();
1019  }
1020 
1021  if (t.y > 0.0) {
1022  const real f = linearMap(t.y, m_minForce, m_maxForce, 0.0, 1.0);
1023  m_neuronsIterator->setInput(applyNoise(f, 0.0, 1.0));
1024  m_neuronsIterator->nextNeuron();
1025  m_neuronsIterator->setInput(0.0);
1026  m_neuronsIterator->nextNeuron();
1027  } else {
1028  const real f = linearMap(-t.y, m_minForce, m_maxForce, 0.0, 1.0);
1029  m_neuronsIterator->setInput(0.0);
1030  m_neuronsIterator->nextNeuron();
1031  m_neuronsIterator->setInput(applyNoise(f, 0.0, 1.0));
1032  m_neuronsIterator->nextNeuron();
1033  }
1034 
1035  // Updating graphical representation if we have to
1036  if (m_drawSensor) {
1037  // We only draw the x and y components of the vector
1038  m_graphics->setVector(wVector(t.x, t.y, 0.0));
1039  }
1040 }
1041 
1043 {
1044  return 4;
1045 }
1046 
1047 void MarXbotTractionSensor::resourceChanged(QString resourceName, ResourceChangeType changeType)
1048 {
1049  // Calling parent function
1050  MarXbotSensor::resourceChanged(resourceName, changeType);
1051 
1052  if (changeType == Deleted) {
1053  return;
1054  }
1055 
1056  if (resourceName == m_marxbotResource) {
1057  m_robot = getResource<PhyMarXbot>();
1058 
1059  // Eanbling sensors
1060  m_robot->tractionSensorController()->setEnabled(true);
1061 
1062  // If graphics is enabled, creating the graphical object
1063  if (m_drawSensor) {
1064  const wVector offset(0.0, 0.0, PhyMarXbot::basez + PhyMarXbot::bodyh + 0.1);
1065 
1066  m_graphics = new TractionSensorGraphic(m_robot, offset, 0.005f, 0.1f / m_maxForce, m_maxForce, m_minForce, "Traction sensor");
1067  }
1068  } else if (resourceName == m_neuronsIteratorResource) {
1069  m_neuronsIterator = getResource<NeuronsIterator>();
1070  m_neuronsIterator->setCurrentBlock(name());
1071  m_neuronsIterator->setGraphicProperties("t+x", 0.0, 1.0, Qt::red);
1072  m_neuronsIterator->nextNeuron();
1073  m_neuronsIterator->setGraphicProperties("t-x", 0.0, 1.0, Qt::red);
1074  m_neuronsIterator->nextNeuron();
1075  m_neuronsIterator->setGraphicProperties("t+y", 0.0, 1.0, Qt::red);
1076  m_neuronsIterator->nextNeuron();
1077  m_neuronsIterator->setGraphicProperties("t-y", 0.0, 1.0, Qt::red);
1078  } else {
1079  Logger::info("Unknown resource " + resourceName + " for " + name());
1080  }
1081 }
1082 
1084  MarXbotSensor(params, prefix),
1085  m_robot(NULL),
1086  m_arena(NULL),
1087  m_neuronsIterator(NULL),
1088  m_activeSensors(ConfigurationHelper::getBoolVector(params, prefix + "activeSensors", "111111111111111111111111")),
1089  m_averageNum(ConfigurationHelper::getInt(params, prefix + "averageNum", 0)),
1090  m_numActiveSensors((m_averageNum == 0) ? m_activeSensors.count(true) : (24 / m_averageNum)),
1091  m_roundSamples(ConfigurationHelper::getString(params, prefix + "roundSamples", "round.sam")),
1092  m_smallSamples(ConfigurationHelper::getString(params, prefix + "smallSamples", "small.sam")),
1093  m_wallSamples(ConfigurationHelper::getString(params, prefix + "wallSamples", "wall.sam"))
1094 {
1095  if (m_activeSensors.size() != 24) {
1096  ConfigurationHelper::throwUserConfigError(prefix + "activeSensors", params.getValue(prefix + "activeSensors"), "The parameter must be a list of exactly 24 elements either equal to 1 or to 0 (do not use any space to separate elements, just put them directly one after the other)");
1097  }
1098 
1099  if ((m_averageNum != 0) && (m_averageNum != 2) && (m_averageNum != 3) && (m_averageNum != 4) && (m_averageNum != 6)) {
1100  ConfigurationHelper::throwUserConfigError(prefix + "averageNum", params.getValue(prefix + "averageNum"), "The parameter can only be 0, 2, 3, 4 or 6");
1101  }
1102 
1103  // Checking that the sampled files have the right number of IR sensors
1104  if (m_roundSamples.numIR() != 24) {
1105  ConfigurationHelper::throwUserConfigError(prefix + "roundSamples", m_roundSamples.filename(), "The file has samples for the wrong number of sensors, expected 24, got " + QString::number(m_roundSamples.numIR()));
1106  }
1107  if (m_smallSamples.numIR() != 24) {
1108  ConfigurationHelper::throwUserConfigError(prefix + "smallSamples", m_smallSamples.filename(), "The file has samples for the wrong number of sensors, expected 24, got " + QString::number(m_smallSamples.numIR()));
1109  }
1110  if (m_wallSamples.numIR() != 24) {
1111  ConfigurationHelper::throwUserConfigError(prefix + "wallSamples", m_wallSamples.filename(), "The file has samples for the wrong number of sensors, expected 8, got " + QString::number(m_wallSamples.numIR()));
1112  }
1113 
1114  // Here we also need the arena to work
1115  addUsableResource("arena");
1116 }
1117 
1119 {
1120  // Nothing to do here
1121 }
1122 
1124 {
1125  // Calling parent function
1126  MarXbotSensor::save(params, prefix);
1127 
1128  // Saving parameters
1129  params.startObjectParameters(prefix, "MarXbotSampledProximityIRSensor", this);
1130  QString activeSensorsString;
1131  for (int i = 0; i < m_activeSensors.size(); i++) {
1132  activeSensorsString += (m_activeSensors[i] ? "1" : "0");
1133  }
1134  params.createParameter(prefix, "activeSensors", activeSensorsString);
1135  params.createParameter(prefix, "averageNum", QString::number(m_averageNum));
1136  params.createParameter(prefix, "roundSamples", m_roundSamples.filename());
1137  params.createParameter(prefix, "smallSamples", m_smallSamples.filename());
1138  params.createParameter(prefix, "wallSamples", m_wallSamples.filename());
1139 }
1140 
1142 {
1143  // Calling parent function
1145 
1146  // Describing our parameters
1147  Descriptor d = addTypeDescription(type, "The sampled proximity infrared sensors of the MarXbot", "This is the sampled version of the proximity infrared sensors of the MarXbot. This sensor only works with objects created using the Arena");
1148  d.describeString("activeSensors").def("111111111111111111111111").help("Which IR sensors of the robot are actually enabled", "This is a string of exactly 24 elements. Each element can be either \"0\" or \"1\" to respectively disable/enable the corresponding proximity IR sensor. The first sensor is the one on the left side of the robot and the others follow counterclockwise (i.e. left, back, right, front)");
1149  d.describeInt("averageNum").def(0).limits(0, 6).help("How many sensors should be averaged", "This can only be 0, 2, 3, 4 or 6. If 2, for each couple of consecutive sensors the average is returned, if 3 for each triplet of consecutive sensors the average is returned and so on. If this is zero, no average is computed and the activeSensors parameter is used. The default value is 0");
1150  d.describeString("roundSamples").def("round.sam").help("The name of the file with samples for big round objects");
1151  d.describeString("smallSamples").def("small.sam").help("The name of the file with samples for small round objects");
1152  d.describeString("wallSamples").def("wall.sam").help("The name of the file with samples for walls");
1153 }
1154 
1156 {
1157  // Checking all resources we need exist
1159 
1160  // Acquiring the lock to get resources
1161  ResourcesLocker locker(this);
1162 
1163  // Getting the list of objects in the arena
1164  const QVector<PhyObject2DWrapper*>& objectsList = m_arena->getObjects();
1165 
1166  // Preparing the vector with activations and setting all values to 0
1167  QVector<real> activations(m_activeSensors.size(), 0.0);
1168 
1169  // Cycling through the list of objects. We first need to get the current position and orientation of the robot
1170  //const wVector robotPos = m_robot->position();
1171  //const real robotAng = m_robot->orientation(m_arena->getPlane());
1172  foreach(const PhyObject2DWrapper* obj, objectsList) {
1173  // Computing angle and distance. We don't need to remove the robot to which this sensor belongs because
1174  // the calculatations will give a negative distance
1175  double distance;
1176  double angle;
1177 
1178  // If computeDistanceAndOrientationFromRobot returns false, we have to discard this object
1179  if (!obj->computeDistanceAndOrientationFromRobot(*(m_arena->getRobotWrapper(m_marxbotResource)), distance, angle)) {
1180  continue;
1181  }
1182 
1183  // Getting the activation. The switch is to understand which samples to use
1184  QVector<unsigned int>::const_iterator actIt = QVector<unsigned int>::const_iterator();
1185  switch (obj->type()) {
1186  case PhyObject2DWrapper::Wall:
1187  actIt = m_wallSamples.getActivation(distance, angle);
1188  break;
1189  case PhyObject2DWrapper::SmallCylinder:
1190  actIt = m_smallSamples.getActivation(distance, angle);
1191  break;
1192  case PhyObject2DWrapper::BigCylinder:
1193  case PhyObject2DWrapper::WheeledRobot:
1194  actIt = m_roundSamples.getActivation(distance, angle);
1195  break;
1196  default:
1197  //Logger::warning("The sampled infrared sensor only works with Small Cylinders, Big Cylinders, Walls and other Robots");
1198  continue;
1199  }
1200 
1201  // Adding activations in the activations vector
1202  for (QVector<real>::iterator it = activations.begin(); it != activations.end(); ++it, ++actIt) {
1203  *it = min(1.0, *it + (real(*actIt) / 1024.0));
1204  }
1205  }
1206 
1207  // Finally activating neurons
1208  m_neuronsIterator->setCurrentBlock(name());
1209  if (m_averageNum == 0) {
1210  QVector<real>::const_iterator it = activations.constBegin();
1211  QVector<bool>::const_iterator activeIt = m_activeSensors.constBegin();
1212  while (activeIt != m_activeSensors.constEnd()) {
1213  if (*activeIt) {
1214  m_neuronsIterator->setInput(applyNoise(*it, 0.0, 1.0));
1215  m_neuronsIterator->nextNeuron();
1216  }
1217 
1218  ++it;
1219  ++activeIt;
1220  }
1221  } else {
1222  QVector<real>::const_iterator it = activations.constBegin();
1223  while (it != activations.constEnd()) {
1224  real avg = 0.0;
1225  for (int j = 0; j < m_averageNum; ++j, ++it) {
1226  avg += *it;
1227  }
1228  avg /= real(m_averageNum);
1229  m_neuronsIterator->setInput(applyNoise(avg, 0.0, 1.0));
1230  m_neuronsIterator->nextNeuron();
1231  }
1232  }
1233 }
1234 
1236 {
1237  return m_numActiveSensors;
1238 }
1239 
1240 void MarXbotSampledProximityIRSensor::resourceChanged(QString resourceName, ResourceChangeType changeType)
1241 {
1242  // Calling parent function
1243  MarXbotSensor::resourceChanged(resourceName, changeType);
1244 
1245  if (changeType == Deleted) {
1246  return;
1247  }
1248 
1249  if (resourceName == m_marxbotResource) {
1250  m_robot = getResource<MarXbot>();
1251 
1252  // Disabling proximity IR sensors, they are not used here
1253  m_robot->proximityIRSensorController()->setEnabled(false);
1254  } else if (resourceName == m_neuronsIteratorResource) {
1255  m_neuronsIterator = getResource<NeuronsIterator>();
1256  m_neuronsIterator->setCurrentBlock(name());
1257 
1258  // We use the actual sensor ID in the neuron name
1259  if (m_averageNum == 0) {
1260  for (int i = 0; i < m_activeSensors.size(); i++) {
1261  if (m_activeSensors[i]) {
1262  m_neuronsIterator->setGraphicProperties("ir" + QString::number(i), 0.0, 1.0, Qt::red);
1263  m_neuronsIterator->nextNeuron();
1264  }
1265  }
1266  } else {
1267  for (int i = 0; i < m_activeSensors.size(); i += m_averageNum) {
1268  m_neuronsIterator->setGraphicProperties(QString("ir%1-%2").arg(i).arg(i + m_averageNum - 1), 0.0, 1.0, Qt::red);
1269  m_neuronsIterator->nextNeuron();
1270  }
1271  }
1272  } else if (resourceName == "arena") {
1273  // Storing the pointer to the arena
1274  m_arena = getResource<Arena>();
1275  } else {
1276  Logger::info("Unknown resource " + resourceName + " for " + name());
1277  }
1278 }
1279 
1281  MarXbotSensor(params, prefix),
1282  m_robot(NULL),
1283  m_neuronsIterator(NULL),
1284  m_enablePosition(ConfigurationHelper::getBool(params, prefix + "enablePosition", true)),
1285  m_enableStatus(ConfigurationHelper::getBool(params, prefix + "enableStatus", true)),
1286  m_enableAttached(ConfigurationHelper::getBool(params, prefix + "enableAttached", true)),
1287  m_enableOtherAttached(ConfigurationHelper::getBool(params, prefix + "enableOtherAttached", true)),
1288  m_numInputs((m_enablePosition ? 2 : 0) + (m_enableStatus ? 1 : 0) + (m_enableAttached ? 1 : 0) + (m_enableOtherAttached ? 1 : 0))
1289 {
1290 }
1291 
1293 {
1294  // Nothing to do here
1295 }
1296 
1298 {
1299  // Calling parent function
1300  MarXbotSensor::save(params, prefix);
1301 
1302  // Saving parameters
1303  params.startObjectParameters(prefix, "MarXbotAttachmentDeviceSensor", this);
1304  params.createParameter(prefix, "enablePosition", (m_enablePosition ? "true" : "false"));
1305  params.createParameter(prefix, "enableStatus", (m_enableStatus ? "true" : "false"));
1306  params.createParameter(prefix, "enableAttached", (m_enableAttached ? "true" : "false"));
1307  params.createParameter(prefix, "enableOtherAttached", (m_enableOtherAttached ? "true" : "false"));
1308 }
1309 
1311 {
1312  // Calling parent function
1314 
1315  // Describing our parameters
1316  Descriptor d = addTypeDescription(type, "The sensor providing the attachment device proprioception", "This sensor provides information about the current status of the attachment device. It provides several inputs (which can be disabled using parameters). The position of the gripper is provided using two neurons (the sin() and the cos() of the angle) to alleviate the problem of 0° and 360° being the same angle with opposite activations.");
1317  d.describeBool("enablePosition").def(true).help("Whether inputs with the position of the attachment device should be enabled or not (default: true)");
1318  d.describeBool("enableStatus").def(true).help("Whether the input with the status of the attachment device should be enabled or not (default: true)");
1319  d.describeBool("enableAttached").def(true).help("Whether the input telling if this robot is attached to another robot should be enabled or not (default: true)");
1320  d.describeBool("enableOtherAttached").def(true).help("Whether the input telling if another robot is attached to this robot should be enabled or not (default: true)");
1321 }
1322 
1324 {
1325  // Checking all resources we need exist
1327 
1328  // Acquiring the lock to get resources
1329  ResourcesLocker locker(this);
1330 
1331  // Getting the motor controller for the attachment device
1333 
1334  // Now reading values
1335  m_neuronsIterator->setCurrentBlock(name());
1336  if (m_enablePosition) {
1337  const real pos = ctrl->getPosition();
1338  m_neuronsIterator->setInput(sin(pos) * 0.5 + 0.5);
1339  m_neuronsIterator->nextNeuron();
1340  m_neuronsIterator->setInput(cos(pos) * 0.5 + 0.5);
1341  m_neuronsIterator->nextNeuron();
1342  }
1343  if (m_enableStatus) {
1344  switch (ctrl->getStatus()) {
1345  case MarXbotAttachmentDeviceMotorController::Open:
1346  m_neuronsIterator->setInput(0.0);
1347  break;
1348  case MarXbotAttachmentDeviceMotorController::HalfClosed:
1349  m_neuronsIterator->setInput(0.5);
1350  break;
1351  case MarXbotAttachmentDeviceMotorController::Closed:
1352  m_neuronsIterator->setInput(1.0);
1353  break;
1354  }
1355  m_neuronsIterator->nextNeuron();
1356  }
1357  if (m_enableAttached) {
1358  if (ctrl->attachedToRobot()) {
1359  m_neuronsIterator->setInput(1.0);
1360  } else {
1361  m_neuronsIterator->setInput(0.0);
1362  }
1363  m_neuronsIterator->nextNeuron();
1364  }
1365  if (m_enableOtherAttached) {
1366  if (ctrl->otherAttachedToUs()) {
1367  m_neuronsIterator->setInput(1.0);
1368  } else {
1369  m_neuronsIterator->setInput(0.0);
1370  }
1371  m_neuronsIterator->nextNeuron();
1372  }
1373 }
1374 
1376 {
1377  return m_numInputs;
1378 }
1379 
1380 void MarXbotAttachmentDeviceSensor::resourceChanged(QString resourceName, ResourceChangeType changeType)
1381 {
1382  // Calling parent function
1383  MarXbotSensor::resourceChanged(resourceName, changeType);
1384 
1385  if (changeType == Deleted) {
1386  return;
1387  }
1388 
1389  if (resourceName == m_marxbotResource) {
1390  m_robot = getResource<MarXbot>();
1391 
1392  // Enabling the attachment device and its motor controller
1393  m_robot->enableAttachmentDevice(true);
1394  m_robot->attachmentDeviceController()->setEnabled(true);
1395  } else if (resourceName == m_neuronsIteratorResource) {
1396  m_neuronsIterator = getResource<NeuronsIterator>();
1397  m_neuronsIterator->setCurrentBlock(name());
1398 
1399  // Creating labels depending on which inputs are activated
1400  if (m_enablePosition) {
1401  m_neuronsIterator->setGraphicProperties("aps", 0.0, 1.0, Qt::red);
1402  m_neuronsIterator->nextNeuron();
1403  m_neuronsIterator->setGraphicProperties("apc", 0.0, 1.0, Qt::red);
1404  m_neuronsIterator->nextNeuron();
1405  }
1406  if (m_enableStatus) {
1407  m_neuronsIterator->setGraphicProperties("as", 0.0, 1.0, Qt::red);
1408  m_neuronsIterator->nextNeuron();
1409  }
1410  if (m_enableAttached) {
1411  m_neuronsIterator->setGraphicProperties("aa", 0.0, 1.0, Qt::red);
1412  m_neuronsIterator->nextNeuron();
1413  }
1414  if (m_enableOtherAttached) {
1415  m_neuronsIterator->setGraphicProperties("ao", 0.0, 1.0, Qt::red);
1416  m_neuronsIterator->nextNeuron();
1417  }
1418  } else {
1419  Logger::info("Unknown resource " + resourceName + " for " + name());
1420  }
1421 }
1422 
1424 {
1425  switch (mode) {
1426  case AbsoluteMode:
1427  return "Absolute";
1428  case DeltaMode:
1429  return "Delta";
1430  default:
1431  return "Unknown";
1432  }
1433 
1434  return "UnknownMode";
1435 
1436 }
1437 
1439 {
1440  mode = mode.toUpper();
1441 
1442  if (mode == "ABSOLUTE") {
1443  return AbsoluteMode;
1444  } else if (mode == "DELTA") {
1445  return DeltaMode;
1446  } else {
1447  return UnknownMode;
1448  }
1449 
1450  return UnknownMode;
1451 }
1452 
1454  MarXbotSensor(params, prefix),
1455  m_robot(NULL),
1456  m_neuronsIterator(NULL),
1457  m_mode(stringToMode(ConfigurationHelper::getString(params, prefix + "mode", "Absolute")))
1458 {
1459  if (m_mode == UnknownMode) {
1460  ConfigurationHelper::throwUserConfigError(prefix + "mode", params.getValue(prefix + "mode"), "The parameter must be one of \"Absolute\" or \"Delta\" (case insensitive)");
1461  }
1462 }
1463 
1465 {
1466  // Nothing to do here
1467 }
1468 
1470 {
1471  // Calling parent function
1472  MarXbotSensor::save(params, prefix);
1473 
1474  // Saving parameters
1475  params.startObjectParameters(prefix, "MarXbotWheelSpeedsSensor", this);
1476  params.createParameter(prefix, "mode", modeToString(m_mode));
1477 }
1478 
1480 {
1481  // Calling parent function
1483 
1484  // Describing our parameters
1485  Descriptor d = addTypeDescription(type, "The sensor reporting the actual velocity of the wheels of the MarXbot", "This sensor have three modalities, see the mode parameter");
1486  d.describeEnum("mode").def("Absolute").values(QStringList() << "Absolute" << "Delta").help("The modality of the sensor", "The possible modalities are: \"Absolute\" meaning that the senors returns the current velocity of the wheels (scaled between -1 and 1) and \"Delta\", meaning that the sensor returns the absolute value of the difference between the desired velocity and the current velocity. The default value is \"Absolute\"");
1487 }
1488 
1490 {
1491  // Checking all resources we need exist
1493 
1494  // Acquiring the lock to get resources
1495  ResourcesLocker locker(this);
1496 
1497  // Getting the motor controller for the attachment device
1498  const WheelMotorController *const ctrl = m_robot->wheelsController();
1499 
1500  // Setting the current block to update the input neurons
1501  m_neuronsIterator->setCurrentBlock(name());
1502 
1503  // Now reading values of the current and desired velocity
1504  double curVel1;
1505  double curVel2;
1506  double desVel1;
1507  double desVel2;
1508  double minSpeed1;
1509  double minSpeed2;
1510  double maxSpeed1;
1511  double maxSpeed2;
1512  ctrl->getSpeeds(curVel1, curVel2);
1513  ctrl->getDesiredSpeeds(desVel1, desVel2);
1514  ctrl->getSpeedLimits(minSpeed1, minSpeed2, maxSpeed1, maxSpeed2);
1515  double nCurVel1 = linearMap(curVel1, minSpeed1, maxSpeed1, -1.0, 1.0);
1516  double nCurVel2 = linearMap(curVel2, minSpeed2, maxSpeed2, -1.0, 1.0);
1517  double nDesVel1 = linearMap(desVel1, minSpeed1, maxSpeed1, -1.0, 1.0);
1518  double nDesVel2 = linearMap(desVel2, minSpeed2, maxSpeed2, -1.0, 1.0);
1519  switch (m_mode) {
1520  case AbsoluteMode:
1521  m_neuronsIterator->setInput(applyNoise(nCurVel1, -1.0, 1.0));
1522  m_neuronsIterator->nextNeuron();
1523  m_neuronsIterator->setInput(applyNoise(nCurVel2, -1.0, 1.0));
1524  m_neuronsIterator->nextNeuron();
1525  break;
1526  case DeltaMode:
1527  m_neuronsIterator->setInput(applyNoise(min(1.0, fabs(nDesVel1 - nCurVel1)), 0.0, 1.0));
1528  m_neuronsIterator->nextNeuron();
1529  m_neuronsIterator->setInput(applyNoise(min(1.0, fabs(nDesVel2 - nCurVel2)), 0.0, 1.0));
1530  m_neuronsIterator->nextNeuron();
1531  break;
1532  default:
1533  // We should never get here
1534  throwUserRuntimeError("Invalid mode for MarXbotWheelSpeedsSensor");
1535  break;
1536  }
1537 }
1538 
1540 {
1541  return 2;
1542 }
1543 
1544 void MarXbotWheelSpeedsSensor::resourceChanged(QString resourceName, ResourceChangeType changeType)
1545 {
1546  // Calling parent function
1547  MarXbotSensor::resourceChanged(resourceName, changeType);
1548 
1549  if (changeType == Deleted) {
1550  return;
1551  }
1552 
1553  if (resourceName == m_marxbotResource) {
1554  m_robot = getResource<MarXbot>();
1555  } else if (resourceName == m_neuronsIteratorResource) {
1556  m_neuronsIterator = getResource<NeuronsIterator>();
1557  m_neuronsIterator->setCurrentBlock(name());
1558 
1559  // Creating labels
1560  real minNeuronValue = 0.0;
1561  real maxNeuronValue = 1.0;
1562  switch (m_mode) {
1563  case AbsoluteMode:
1564  minNeuronValue = -1.0;
1565  maxNeuronValue = 1.0;
1566  break;
1567  case DeltaMode:
1568  minNeuronValue = 0.0;
1569  maxNeuronValue = 1.0;
1570  break;
1571  default:
1572  // We should never get here
1573  minNeuronValue = 0.0;
1574  maxNeuronValue = 1.0;
1575  break;
1576  }
1577  m_neuronsIterator->setGraphicProperties("w0", minNeuronValue, maxNeuronValue, Qt::red);
1578  m_neuronsIterator->nextNeuron();
1579  m_neuronsIterator->setGraphicProperties("w1", minNeuronValue, maxNeuronValue, Qt::red);
1580  m_neuronsIterator->nextNeuron();
1581  } else {
1582  Logger::info("Unknown resource " + resourceName + " for " + name());
1583  }
1584 }
1585 
1586 /*FRONT*/
1588  MarXbotSensor(params, prefix),
1589  m_robot(NULL),
1590  m_neuronsIterator(NULL),
1591  m_sensorLeft(NULL),
1592  m_sensorCenter(NULL),
1593  m_sensorRight(NULL),
1594  m_maxDistance(ConfigurationHelper::getDouble(params, prefix + "maxDistance", 1.0)),
1595  m_aperture(ConfigurationHelper::getDouble(params, prefix + "aperture", 60.0)),
1596  m_drawSensors(ConfigurationHelper::getBool(params, prefix + "drawSensors", false)),
1597  m_drawRays(ConfigurationHelper::getBool(params, prefix + "drawRays", false)),
1598  m_drawRaysRange(ConfigurationHelper::getBool(params, prefix + "drawRaysRange", false))
1599 {
1600  // Sanity check
1601  if (m_maxDistance <= 0.0f) {
1602  ConfigurationHelper::throwUserConfigError(prefix + "maxDistance", params.getValue(prefix + "maxDistance"), "The parameter must be a positive real number");
1603  } else if ((m_aperture < 0.0f) || (m_aperture > 360.0f)) {
1604  ConfigurationHelper::throwUserConfigError(prefix + "aperture", params.getValue(prefix + "aperture"), "The parameter must be a positive real number smaller than 360");
1605  }
1606 }
1607 
1609 {
1610  delete m_sensorLeft;
1611  delete m_sensorCenter;
1612  delete m_sensorRight;
1613 }
1614 
1616 {
1617  // Calling parent function
1618  MarXbotSensor::save(params, prefix);
1619 
1620  // Saving parameters
1621  params.startObjectParameters(prefix, "MarXbotLaserFrontDistanceSensor", this);
1622  params.createParameter(prefix, "maxDistance", QString::number(m_maxDistance));
1623  params.createParameter(prefix, "aperture", QString::number(m_maxDistance));
1624  params.createParameter(prefix, "drawSensors", m_drawSensors ? QString("true") : QString("false"));
1625  params.createParameter(prefix, "drawRays", m_drawRays ? QString("true") : QString("false"));
1626  params.createParameter(prefix, "drawRaysRange", m_drawRaysRange ? QString("true") : QString("false"));
1627 }
1628 
1630 {
1631  // Calling parent function
1633 
1634  // Describing our parameters
1635  Descriptor d = addTypeDescription(type, "A frontal distance sensor for long distances", "This is a simple distance sensor in the frontal part of the robot with three rays, at -30��, 0�� and 30�� with respect to the frontal part of the robot. This could be implemented on the real robot using the laser scanner.");
1636  d.describeReal("maxDistance").def(1.0).limits(0.0f, +Infinity).help("The maximum distance of the sensors");
1637  d.describeReal("aperture").def(60.0).limits(0.0f, 360.0f).help("The sensor aperture in degrees");
1638  d.describeBool("drawSensors").def(false).help("Whether to draw the sensors or not");
1639  d.describeBool("drawRays").def(false).help("When drawing the sensor, whether to draw the rays or not");
1640  d.describeBool("drawRaysRange").def(false).help("When drawing the rays, whether to draw the real range or not");
1641 }
1642 
1644 {
1645  // Checking all resources we need exist
1647 
1648  // Acquiring the lock to get resources
1649  ResourcesLocker locker(this);
1650 
1651  // Setting the current block to update the input neurons
1652  m_neuronsIterator->setCurrentBlock(name());
1653 
1654  // Now reading values from the sensor
1655  m_sensorLeft->update();
1656  m_sensorCenter->update();
1657  m_sensorRight->update();
1658 
1659  m_neuronsIterator->setInput(applyNoise(1.0 - m_sensorLeft->getRayCastHit().distance, 0.0, 1.0));
1660  m_neuronsIterator->nextNeuron();
1661  m_neuronsIterator->setInput(applyNoise(1.0 - m_sensorCenter->getRayCastHit().distance, 0.0, 1.0));
1662  m_neuronsIterator->nextNeuron();
1663  m_neuronsIterator->setInput(applyNoise(1.0 - m_sensorRight->getRayCastHit().distance, 0.0, 1.0));
1664  m_neuronsIterator->nextNeuron();
1665 }
1666 
1668 {
1669  return 3;
1670 }
1671 
1672 void MarXbotLaserFrontDistanceSensor::resourceChanged(QString resourceName, ResourceChangeType changeType)
1673 {
1674  // Calling parent function
1675  MarXbotSensor::resourceChanged(resourceName, changeType);
1676 
1677  if (changeType == Deleted) {
1678  return;
1679  }
1680 
1681  if (resourceName == m_marxbotResource) {
1682  m_robot = getResource<MarXbot>();
1683 
1684  // Deleting the old sensors and creating a new ones
1685  delete m_sensorLeft;
1686  delete m_sensorCenter;
1687  delete m_sensorRight;
1688 
1689  wMatrix centralMtr = wMatrix::pitch(PI_GRECO / 2.0f);
1690  centralMtr.w_pos = wVector(0.0, -PhyMarXbot::bodyr, PhyMarXbot::basez + PhyMarXbot::trackradius * 2.0f + PhyMarXbot::treaddepth);
1691  m_sensorCenter = new SingleIR(m_robot, centralMtr, 0.02f, m_maxDistance, 0.0f, 1);
1692  m_sensorCenter->setGraphicalProperties(m_drawSensors, m_drawRays, m_drawRaysRange);
1693 
1694  wMatrix mtr = wMatrix::yaw(toRad(m_aperture / 2.0f)) * centralMtr;
1695  m_sensorLeft = new SingleIR(m_robot, mtr, 0.02f, m_maxDistance, 0.0f, 1);
1696  m_sensorLeft->setGraphicalProperties(m_drawSensors, m_drawRays, m_drawRaysRange);
1697 
1698  mtr = wMatrix::yaw(toRad(-m_aperture / 2.0f)) * centralMtr;
1699  m_sensorRight = new SingleIR(m_robot, mtr, 0.02f, m_maxDistance, 0.0f, 1);
1700  m_sensorRight->setGraphicalProperties(m_drawSensors, m_drawRays, m_drawRaysRange);
1701  } else if (resourceName == m_neuronsIteratorResource) {
1702  m_neuronsIterator = getResource<NeuronsIterator>();
1703  m_neuronsIterator->setCurrentBlock(name());
1704 
1705  // Creating labels
1706  m_neuronsIterator->setGraphicProperties("l0", 0.0, 1.0, Qt::red);
1707  m_neuronsIterator->nextNeuron();
1708  m_neuronsIterator->setGraphicProperties("l1", 0.0, 1.0, Qt::red);
1709  m_neuronsIterator->nextNeuron();
1710  m_neuronsIterator->setGraphicProperties("l2", 0.0, 1.0, Qt::red);
1711  m_neuronsIterator->nextNeuron();
1712  } else {
1713  Logger::info("Unknown resource " + resourceName + " for " + name());
1714  }
1715 }
1716 
1717 /*OMNI*/
1718 
1720  MarXbotSensor(params, prefix),
1721  m_robot(NULL),
1722  m_neuronsIterator(NULL),
1723  m_sensorLeft(NULL),
1724  m_sensorCenter(NULL),
1725  m_sensorRight(NULL),
1726  m_sensorRearLeft(NULL),
1727  m_sensorRear(NULL),
1728  m_sensorRearRight(NULL),
1729  m_maxDistance(ConfigurationHelper::getDouble(params, prefix + "maxDistance", 1.0)),
1730  m_drawSensors(ConfigurationHelper::getBool(params, prefix + "drawSensors", false)),
1731  m_drawRays(ConfigurationHelper::getBool(params, prefix + "drawRays", false)),
1732  m_drawRaysRange(ConfigurationHelper::getBool(params, prefix + "drawRaysRange", false)),
1733  m_avgSensors(ConfigurationHelper::getBool(params, prefix + "averageSensors", false))
1734 {
1735  // Sanity check
1736  if (m_maxDistance <= 0.0f) {
1737  ConfigurationHelper::throwUserConfigError(prefix + "maxDistance", params.getValue(prefix + "maxDistance"), "The parameter must be a positive real number");
1738  }
1739 }
1740 
1742 {
1743  delete m_sensorLeft;
1744  delete m_sensorCenter;
1745  delete m_sensorRight;
1746  delete m_sensorRearLeft;
1747  delete m_sensorRear;
1748  delete m_sensorRearRight;
1749 }
1750 
1752 {
1753  // Calling parent function
1754  MarXbotSensor::save(params, prefix);
1755 
1756  // Saving parameters
1757  params.startObjectParameters(prefix, "MarXbotLaserOmniDistanceSensor", this);
1758  params.createParameter(prefix, "maxDistance", QString::number(m_maxDistance));
1759  params.createParameter(prefix, "drawSensors", m_drawSensors ? QString("true") : QString("false"));
1760  params.createParameter(prefix, "drawRays", m_drawRays ? QString("true") : QString("false"));
1761  params.createParameter(prefix, "drawRaysRange", m_drawRaysRange ? QString("true") : QString("false"));
1762  params.createParameter(prefix, "averageSensors", m_avgSensors? QString("true") : QString("false"));
1763 }
1764 
1766 {
1767  // Calling parent function
1769 
1770  // Describing our parameters
1771  Descriptor d = addTypeDescription(type, "An omnidirection distance sensor for long distances", "This is a simple distance sensor in the frontal and rear part of the robot with six rays, each 60° starting in the frontal part of the robot. This could be implemented on the real robot using the laser scanner.");
1772  d.describeReal("maxDistance").def(1.0).limits(0.0f, +Infinity).help("The maximum distance of the sensors");
1773  d.describeBool("drawSensors").def(false).help("Whether to draw the sensors or not");
1774  d.describeBool("drawRays").def(false).help("When drawing the sensor, whether to draw the rays or not");
1775  d.describeBool("drawRaysRange").def(false).help("When drawing the rays, whether to draw the real range or not");
1776  d.describeBool("averageSensors").def(false).help("Whether the sensors should be averaged");
1777 }
1778 
1780 {
1781  // Checking all resources we need exist
1783 
1784  // Acquiring the lock to get resources
1785  ResourcesLocker locker(this);
1786 
1787  // Setting the current block to update the input neurons
1788  m_neuronsIterator->setCurrentBlock(name());
1789 
1790  // Now reading values from the sensor
1791  m_sensorLeft->update();
1792  m_sensorCenter->update();
1793  m_sensorRight->update();
1794  m_sensorRearLeft->update();
1795  m_sensorRear->update();
1796  m_sensorRearRight->update();
1797 
1798 
1799  if(m_avgSensors){
1800  double avg = 0.0;
1801  avg += m_sensorLeft->getRayCastHit().distance;
1802  avg += m_sensorCenter->getRayCastHit().distance;
1803  avg += m_sensorRight->getRayCastHit().distance;
1804  avg += m_sensorRearLeft->getRayCastHit().distance;
1805  avg += m_sensorRear->getRayCastHit().distance;
1806  avg += m_sensorRearRight->getRayCastHit().distance;
1807  avg /= 6.0;
1808  m_neuronsIterator->setInput(applyNoise(1.0 - avg, 0.0, 1.0));
1809  m_neuronsIterator->nextNeuron();
1810  }else{
1811  m_neuronsIterator->setInput(applyNoise(1.0 - m_sensorLeft->getRayCastHit().distance, 0.0, 1.0));
1812  m_neuronsIterator->nextNeuron();
1813  m_neuronsIterator->setInput(applyNoise(1.0 - m_sensorCenter->getRayCastHit().distance, 0.0, 1.0));
1814  m_neuronsIterator->nextNeuron();
1815  m_neuronsIterator->setInput(applyNoise(1.0 - m_sensorRight->getRayCastHit().distance, 0.0, 1.0));
1816  m_neuronsIterator->nextNeuron();
1817  m_neuronsIterator->setInput(applyNoise(1.0 - m_sensorRearLeft->getRayCastHit().distance, 0.0, 1.0));
1818  m_neuronsIterator->nextNeuron();
1819  m_neuronsIterator->setInput(applyNoise(1.0 - m_sensorRear->getRayCastHit().distance, 0.0, 1.0));
1820  m_neuronsIterator->nextNeuron();
1821  m_neuronsIterator->setInput(applyNoise(1.0 - m_sensorRearRight->getRayCastHit().distance, 0.0, 1.0));
1822  m_neuronsIterator->nextNeuron();
1823  }
1824 }
1825 
1827 {
1828  if(m_avgSensors)
1829  return 1;
1830  else
1831  return 6;
1832 }
1833 
1834 void MarXbotLaserOmniDistanceSensor::resourceChanged(QString resourceName, ResourceChangeType changeType)
1835 {
1836  // Calling parent function
1837  MarXbotSensor::resourceChanged(resourceName, changeType);
1838 
1839  if (changeType == Deleted) {
1840  return;
1841  }
1842 
1843 
1844  if (resourceName == m_marxbotResource) {
1845  m_robot = getResource<MarXbot>();
1846 
1847  // Deleting the old sensors and creating a new ones
1848  delete m_sensorLeft;
1849  delete m_sensorCenter;
1850  delete m_sensorRight;
1851  delete m_sensorRearLeft;
1852  delete m_sensorRear;
1853  delete m_sensorRearRight;
1854 
1855  wMatrix centralMtr = wMatrix::pitch(PI_GRECO / 2.0f);
1856  centralMtr.w_pos = wVector(0.0, 0.0, PhyMarXbot::basez + PhyMarXbot::trackradius * 2.0f + PhyMarXbot::treaddepth);
1857  m_sensorCenter = new SingleIR(m_robot, centralMtr, PhyMarXbot::bodyr+0.008f, m_maxDistance, 0.0f, 1);
1858  m_sensorCenter->setGraphicalProperties(m_drawSensors, m_drawRays, m_drawRaysRange);
1859 
1860  wMatrix mtr = wMatrix::yaw(toRad(60.0)) * centralMtr;
1861  m_sensorLeft = new SingleIR(m_robot, mtr, PhyMarXbot::bodyr+0.005f, m_maxDistance, 0.0f, 1);
1862  m_sensorLeft->setGraphicalProperties(m_drawSensors, m_drawRays, m_drawRaysRange);
1863 
1864  mtr = wMatrix::yaw(toRad(120.0)) * centralMtr;
1865  m_sensorRearLeft = new SingleIR(m_robot, mtr, PhyMarXbot::bodyr+0.005f, m_maxDistance, 0.0f, 1);
1866  m_sensorRearLeft->setGraphicalProperties(m_drawSensors, m_drawRays, m_drawRaysRange);
1867 
1868  mtr = wMatrix::yaw(toRad(180.0)) * centralMtr;
1869  m_sensorRear= new SingleIR(m_robot, mtr, PhyMarXbot::bodyr+0.005f, m_maxDistance, 0.0f, 1);
1870  m_sensorRear->setGraphicalProperties(m_drawSensors, m_drawRays, m_drawRaysRange);
1871 
1872  mtr = wMatrix::yaw(toRad(240)) * centralMtr;
1873  m_sensorRearRight = new SingleIR(m_robot, mtr, PhyMarXbot::bodyr+0.005f, m_maxDistance, 0.0f, 1);
1874  m_sensorRearRight->setGraphicalProperties(m_drawSensors, m_drawRays, m_drawRaysRange);
1875 
1876  mtr = wMatrix::yaw(toRad(300.0)) * centralMtr;
1877  m_sensorRight = new SingleIR(m_robot, mtr, PhyMarXbot::bodyr+0.005f, m_maxDistance, 0.0f, 1);
1878  m_sensorRight->setGraphicalProperties(m_drawSensors, m_drawRays, m_drawRaysRange);
1879 
1880 
1881 
1882 
1883 
1884  } else if (resourceName == m_neuronsIteratorResource) {
1885  m_neuronsIterator = getResource<NeuronsIterator>();
1886  m_neuronsIterator->setCurrentBlock(name());
1887 
1888  if(m_avgSensors){ //if average sensor
1889  m_neuronsIterator->setGraphicProperties("AvgLR", 0.0, 1.0, Qt::red);
1890  m_neuronsIterator->nextNeuron();
1891  }else{
1892  // Creating labels
1893  m_neuronsIterator->setGraphicProperties("l0", 0.0, 1.0, Qt::red);
1894  m_neuronsIterator->nextNeuron();
1895  m_neuronsIterator->setGraphicProperties("l1", 0.0, 1.0, Qt::red);
1896  m_neuronsIterator->nextNeuron();
1897  m_neuronsIterator->setGraphicProperties("l2", 0.0, 1.0, Qt::red);
1898  m_neuronsIterator->nextNeuron();
1899  m_neuronsIterator->setGraphicProperties("l3", 0.0, 1.0, Qt::red);
1900  m_neuronsIterator->nextNeuron();
1901  m_neuronsIterator->setGraphicProperties("l4", 0.0, 1.0, Qt::red);
1902  m_neuronsIterator->nextNeuron();
1903  m_neuronsIterator->setGraphicProperties("l5", 0.0, 1.0, Qt::red);
1904  m_neuronsIterator->nextNeuron();
1905  }
1906  } else {
1907  Logger::info("Unknown resource " + resourceName + " for " + name());
1908  }
1909 }
1910 
1911 
1912 }
void usableResources(QStringList resources)
virtual ~MarXbotAttachmentDeviceSensor()
Destructor.
FARSA_UTIL_TEMPLATE real toRad(real x)
virtual Type type() const =0
Returns the type of this wrapper object.
FARSA_UTIL_TEMPLATE float linearMap(float x, float min=-10, float max=10, float outMin=-1, float outMax=1)
void drawCamera(bool d)
Sets whether to draw the linear camera or not.
Definition: sensors.cpp:1237
virtual void setSensorActive(int i, bool active)
double applyNoise(double v, double minValue, double maxValue) const
Adds noise to the value.
static void describe(QString type)
Generates a description of this class and its parameters.
virtual void save(ConfigurationParameters &params, QString prefix)
Saves current parameters into the given ConfigurationParameters object.
static wMatrix identity()
virtual int size()
Returns the number of neurons required by this sensor.
MarXbotTractionSensor(ConfigurationParameters &params, QString prefix)
Constructor.
static void drawCylinder(wVector axis, wVector centre, float len, float radius, QColor c=Qt::green)
static void describe(QString type)
Describes all the parameters for this sensor.
const RayCastHit & getRayCastHit() const
Mode
The enum of different modalities for this sensor.
virtual ~MarXbotWheelSpeedsSensor()
Destructor.
virtual void save(ConfigurationParameters &params, QString prefix)
Saves current parameters into the given ConfigurationParameters object.
const real m_maxLength
The maximum length of the vector.
const real m_radius
The radius of the arrow. The length depends on the vector intensity.
MarXbotAttachmentDeviceMotorController * attachmentDeviceController()
QString actualResourceNameForMultirobot(QString resourceName) const
Returns the actual resource name to use.
static wMatrix grammSchmidt(const wVector &dir)
void setUseColorTextureOfOwner(bool b)
static QString getString(ConfigurationParameters &params, QString paramPath, QString def=QString())
void addUsableResource(QString resource)
World * world()
static void describe(QString type)
Generates a description of this class and its parameters.
virtual void save(ConfigurationParameters &params, QString prefix)
Saves current parameters into the given ConfigurationParameters object.
MarXbotLaserFrontDistanceSensor(ConfigurationParameters &params, QString prefix)
Constructor.
void setGraphicalProperties(bool drawSensor, bool drawRay=false, bool drawRealRay=false)
QColor color() const
virtual void save(ConfigurationParameters &params, QString prefix)
Saves current parameters into the given ConfigurationParameters object.
static const double Infinity
static void describe(QString type)
Generates a description of this class and its parameters.
QString name()
Return the name of the Sensor.
MarXbotLaserOmniDistanceSensor(ConfigurationParameters &params, QString prefix)
Constructor.
WObject *const m_object
The object to which this representation is attached.
static void describe(QString type)
Generates a description of this class and its parameters.
virtual int size()
Returns the number of neurons required by this sensor.
const WheeledRobot2DWrapper * getRobotWrapper(QString robotName) const
Returns a pointer to the wrapper of a robot given the robot resource name.
Definition: arena.cpp:217
virtual void update()
Performs the sensor update. This also modifies the activation of input neurons.
QMutex m_vectorMutex
The mutex protecting the m_vector vector.
QString m_marxbotResource
The name of the resource associated with the MarXbot robot.
void attachToObject(WObject *object, bool makeOwner=false, const wMatrix &displacement=wMatrix::identity())
virtual bool nextNeuron()=0
Go to the next neuron of the current block.
void setTexture(QString textureName)
virtual bool setCurrentBlock(QString blockName)=0
Set the current blocks of neurons to iterate.
SimulatedIRGroundSensorController * groundBottomIRSensorController()
void update()
Updates the sensor reading.
Definition: sensors.cpp:1109
TractionSensorController * tractionSensorController()
virtual ~MarXbotLaserFrontDistanceSensor()
Destructor.
const QVector< SingleIR > & sensors() const
virtual void shareResourcesWith(ResourcesUser *buddy)
MarXbotLinearCameraSensor(ConfigurationParameters &params, QString prefix)
Constructor.
virtual int size()
Returns the number of neurons required by this sensor.
virtual void save(ConfigurationParameters &params, QString prefix)
Saves current parameters into the given ConfigurationParameters object.
void setColor(QColor c)
static void describe(QString type)
Describe all the parameter for configuring the Sensor.
virtual int size()
Returns the number of neurons required by this sensor.
void setVector(const wVector vector)
Sets the vector to draw. The vector must be in the object frame of reference.
static wMatrix roll(real ang)
static wMatrix pitch(real ang)
virtual void update()
Performs the sensor update. This also modifies the activation of input neurons.
virtual void resourceChanged(QString name, ResourceChangeType changeType)
virtual int size()
Returns the number of neurons required by this sensor.
static void throwUserConfigError(QString paramName, QString paramValue, QString description)
The graphical representation of the MarXbot traction sensor.
static void describe(QString type)
Generates a description of this class and its parameters.
void drawArrow(wVector vector, real radius, real maxTipLength, QColor col, RenderWObject *renderer, QGLContext *gw)
Draws an arrow.
virtual int size()
Returns the number of neurons required by this sensor.
virtual void update()
Performs the sensor update. This also modifies the activation of input neurons.
MarXbotProximityIRSensor(ConfigurationParameters &params, QString prefix)
Constructor.
virtual void render(RenderWObject *renderer, QGLContext *gw)
Performs the actual drawing.
const QColor & colorForReceptor(int i) const
Returns the color perceived by the i-th receptor.
Definition: sensors.h:268
const wMatrix & matrix() const
virtual int size()
Returns the number of neurons required by this sensor.
virtual void update()
Performs the sensor update. This also modifies the activation of input neurons.
virtual int size()
Returns the number of neurons required by this sensor.
const QVector< PhyObject2DWrapper * > & getObjects() const
Returns the list of 2D objects.
Definition: arena.h:136
virtual int size()
Returns the number of neurons required by this sensor.
The base abstract class for the Sensor hierarchy.
virtual int size()
Returns the number of neurons required by this sensor.
unsigned int numIR() const
Returns the number of IR sensors as read from the file.
Definition: sensors.h:879
void setEnabled(bool b)
virtual void update()
Performs the sensor update. This also modifies the activation of input neurons.
virtual ~MarXbotLinearCameraSensor()
Destructor.
virtual ~MarXbotLinearCameraSensorNew()
Destructor.
void getSpeeds(QVector< double > &speeds) const
void FARSA_UTIL_TEMPLATE throwUserRuntimeError(QString reason)
void getSpeedLimits(QVector< double > &minSpeeds, QVector< double > &maxSpeeds) const
static void info(QString msg)
MarXbotAttachmentDeviceSensor(ConfigurationParameters &params, QString prefix)
Constructor.
const real m_scale
The scaling factor for the vector length.
virtual void update()
Performs the sensor update. This also modifies the activation of input neurons.
virtual void save(ConfigurationParameters &params, QString prefix)
Saves the parameters of the sensor into the ConfigurationParameters object.
The base abstract class for MarXbot sensors.
static Mode stringToMode(QString mode)
Converts the given string to a modality.
MarXbotSensor(ConfigurationParameters &params, QString prefix)
Constructor.
virtual void update()
Performs the sensor update. This also modifies the activation of input neurons.
A class wrapping a PhyObject to add methods suitable for wheeled robots simulations.
real limitComponent(real v, bool &limited)
Limits the component to be between m_minLength and m_maxLength.
virtual ~MarXbotProximityIRSensor()
Destructor.
void resetNeededResourcesCheck()
Resets the check on needed resources so that the next call to checkAllNeededResourcesExist() will per...
virtual ~MarXbotSensor()
Destructor.
bool startObjectParameters(QString groupPath, QString typeName, ParameterSettable *object)
virtual ~MarXbotTractionSensor()
Destructor.
static void describe(QString type)
Generates a description of this class and its parameters.
void getDesiredSpeeds(QVector< double > &speeds) const
virtual ~MarXbotGroundBottomIRSensor()
Destructor.
virtual ~MarXbotGroundAroundIRSensor()
Destructor.
const real m_maxTipLength
The maximum length of the tip of the vector.
void drawCamera(bool d)
Sets whether to draw the linear camera or not.
Definition: sensors.cpp:704
static Descriptor addTypeDescription(QString type, QString shortHelp, QString longHelp=QString(""))
QString getValue(QString path, bool alsoMatchParents=false) const
unsigned int getActivation(unsigned int i, real dist, real ang) const
Returns the activation of the given sensor at the given distance and angle.
Definition: sensors.cpp:1373
void update()
Updates the sensor reading.
Definition: sensors.cpp:579
QString m_neuronsIteratorResource
The name of th resource associated with the neural network iterator.
float real
virtual void update()
Performs the sensor update. This also modifies the activation of input neurons.
RenderWObjectContainer * container()
SimulatedIRProximitySensorController * proximityIRSensorController()
virtual void update()
Performs the sensor update. This also modifies the activation of input neurons.
static wMatrix yaw(real ang)
virtual void setInput(double value)=0
Set the input of the current neuron.
void enableAttachmentDevice(bool enable)
virtual ~MarXbotSampledProximityIRSensor()
Destructor.
static QString modeToString(Mode mode)
Returns the string representation of the given modality.
static void describe(QString type)
Generates a description of this class and its parameters.
MarXbotLinearCameraSensorNew(ConfigurationParameters &params, QString prefix)
Constructor.
static void describe(QString type)
Generates a description of this class and its parameters.
static QVector< SimpleInterval > vectorOfSimpleIntervalsFromString(QString s, bool *ok=NULL)
TractionSensorGraphic(WObject *object, const wVector &offset, real radius, real scale=1.0, real maxLength=1.0, real minLength=0.0, QString name="unamed")
Constructor.
MarXbotSampledProximityIRSensor(ConfigurationParameters &params, QString prefix)
Constructor.
virtual ~MarXbotLaserOmniDistanceSensor()
Destructor.
MarXbotWheelSpeedsSensor(ConfigurationParameters &params, QString prefix)
Constructor.
virtual void save(ConfigurationParameters &params, QString prefix)
Saves current parameters into the given ConfigurationParameters object.
static const int MaxInteger
QString name() const
FARSA_UTIL_TEMPLATE const T min(const T &t1, const U &t2)
virtual void save(ConfigurationParameters &params, QString prefix)
Saves current parameters into the given ConfigurationParameters object.
virtual bool computeDistanceAndOrientationFromRobot(const WheeledRobot2DWrapper &robot, double &distance, double &angle) const =0
Computes the distance and orientation of this object respect to the given robot.
static void describe(QString type)
Generates a description of this class and its parameters.
virtual void setGraphicProperties(QString label, double minValue, double maxValue, QColor color)=0
Set the graphic properties for the current neuron (in case it will be visualized on a GUI) ...
MarXbotGroundBottomIRSensor(ConfigurationParameters &params, QString prefix)
Constructor.
double activation(int i) const
static void describe(QString type)
Generates a description of this class and its parameters.
virtual void update()
Performs the sensor update. This also modifies the activation of input neurons.
virtual void resourceChanged(QString resourceName, ResourceChangeType changeType)
The function called when a resource used here is changed.
virtual void save(ConfigurationParameters &params, QString prefix)
Saves current parameters into the given ConfigurationParameters object.
const QColor & colorForReceptor(int i) const
Returns the color perceived by the i-th receptor.
Definition: sensors.h:544
void save(ConfigurationParameters &params, QString prefix)
Save the parameters into the ConfigurationParameters.
void checkAllNeededResourcesExist()
Checks whether all resources we need are existing and throws an exception if they aren't...
wVector transformVector(const wVector &v) const
virtual void update()
Performs the sensor update. This also modifies the activation of input neurons.
static void describe(QString type)
Generates a description of this class and its parameters.
SimulatedIRGroundSensorController * groundAroundIRSensorController()
virtual void save(ConfigurationParameters &params, QString prefix)
Saves current parameters into the given ConfigurationParameters object.
void createParameter(QString groupPath, QString parameter)
virtual void save(ConfigurationParameters &params, QString prefix)
Saves current parameters into the given ConfigurationParameters object.
const QString & filename() const
Returns the name of the file from which samples are loaded.
Definition: sensors.h:869
const real m_minLength
The minimum length of the vector.
void setupColorTexture(QGLContext *, RenderWObject *obj)
virtual void save(ConfigurationParameters &params, QString prefix)
Saves current parameters into the given ConfigurationParameters object.
virtual int size()
Returns the number of neurons required by this sensor.
MarXbotGroundAroundIRSensor(ConfigurationParameters &params, QString prefix)
Constructor.
WheelMotorController * wheelsController()