kheperasensors.cpp
1 
2 /********************************************************************************
3  * FARSA Experiments Library *
4  * Copyright (C) 2007-2012 *
5  * Gianluca Massera <emmegian@yahoo.it> *
6  * Stefano Nolfi <stefano.nolfi@istc.cnr.it> *
7  * Tomassino Ferrauto <tomassino.ferrauto@istc.cnr.it> *
8  * Onofrio Gigliotta <onofrio.gigliotta@istc.cnr.it> *
9  * *
10  * This program is free software; you can redistribute it and/or modify *
11  * it under the terms of the GNU General Public License as published by *
12  * the Free Software Foundation; either version 2 of the License, or *
13  * (at your option) any later version. *
14  * *
15  * This program is distributed in the hope that it will be useful, *
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
18  * GNU General Public License for more details. *
19  * *
20  * You should have received a copy of the GNU General Public License *
21  * along with this program; if not, write to the Free Software *
22  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *
23  ********************************************************************************/
24 
25 #include "kheperasensors.h"
26 #include "configurationhelper.h"
27 #include "logger.h"
28 #include "graphicalwobject.h"
29 #include "arena.h"
30 #include "utilitiesexceptions.h"
31 
32 namespace farsa {
33 
35  Sensor(params, prefix),
36  m_kheperaResource("robot"),
37  m_neuronsIteratorResource("neuronsIterator")
38 {
39  // Reading parameters
42 
43  // Declaring the resources that are needed here
45 }
46 
48 {
49  // Nothing to do here
50 }
51 
52 void KheperaSensor::save(ConfigurationParameters& params, QString prefix)
53 {
54  // Calling parent function
55  Sensor::save(params, prefix);
56 
57  // Saving parameters
58  params.startObjectParameters(prefix, "KheperaSensor", this);
59  params.createParameter(prefix, "khepera", m_kheperaResource);
60  params.createParameter(prefix, "neuronsIterator", m_neuronsIteratorResource);
61 }
62 
63 void KheperaSensor::describe(QString type)
64 {
65  // Calling parent function
66  Sensor::describe(type);
67 
68  // Describing our parameters
69  Descriptor d = addTypeDescription(type, "The base class for Khepera sensors");
70  d.describeString("khepera").def("robot").help("the name of the resource associated with the khepera robot to use (default is \"robot\")");
71  d.describeString("neuronsIterator").def("neuronsIterator").help("the name of the resource associated with the neural network iterator (default is \"neuronsIterator\")");
72 }
73 
74 void KheperaSensor::resourceChanged(QString resourceName, ResourceChangeType changeType)
75 {
76  // Calling parent function
77  Sensor::resourceChanged(resourceName, changeType);
78 
79  // Here we only check whether the resource has been deleted and reset the check flag, the
80  // actual work is done in subclasses
81  if (changeType == Deleted) {
83  return;
84  }
85 }
86 
88  KheperaSensor(params, prefix),
89  m_robot(NULL),
90  m_neuronsIterator(NULL)
91 {
92 }
93 
95 {
96  // Nothing to do here
97 }
98 
100 {
101  // Calling parent function
102  KheperaSensor::save(params, prefix);
103 
104  // Saving parameters
105  params.startObjectParameters(prefix, "KheperaProximityIRSensor", this);
106 }
107 
109 {
110  // Calling parent function
112 
113  // Describing our parameters
114  Descriptor d = addTypeDescription(type, "The infrared proximity sensors of the Khepera robot", "The infrared proximity sensors of the Khepera II robot. These are the very short range IR sensors all around the base");
115 }
116 
118 {
119  // Checking all resources we need exist
121 
122  // Acquiring the lock to get resources
123  ResourcesLocker locker( this );
124 
125  m_neuronsIterator->setCurrentBlock(name());
126  for (int i = 0; i < size(); i++, m_neuronsIterator->nextNeuron()) {
127  m_neuronsIterator->setInput(applyNoise(m_robot->proximityIRSensorController()->activation(i), 0.0, 1.0));
128  }
129 }
130 
132 {
133  return 8;
134 }
135 
136 void KheperaProximityIRSensor::resourceChanged(QString resourceName, ResourceChangeType changeType)
137 {
138  // Calling parent function
139  KheperaSensor::resourceChanged(resourceName, changeType);
140 
141  if (changeType == Deleted) {
142  return;
143  }
144 
145  if (resourceName == m_kheperaResource) {
146  m_robot = getResource<PhyKhepera>();
147 
148  // Eanbling sensors
149  m_robot->proximityIRSensorController()->setEnabled(true);
150  } else if (resourceName == m_neuronsIteratorResource) {
151  m_neuronsIterator = getResource<NeuronsIterator>();
152  m_neuronsIterator->setCurrentBlock(name());
153  for (int i = 0; i < size(); i++, m_neuronsIterator->nextNeuron()) {
154  m_neuronsIterator->setGraphicProperties("ir" + QString::number(i), 0.0, 1.0, Qt::red);
155  }
156  } else {
157  Logger::info("Unknown resource " + resourceName + " for " + name());
158  }
159 }
160 
161 
163  KheperaSensor(params, prefix),
164  m_robot(NULL),
165  m_arena(NULL),
166  m_neuronsIterator(NULL),
167  m_activeSensors(ConfigurationHelper::getBoolVector(params, prefix + "activeSensors", "11111111")),
168  m_numActiveSensors(m_activeSensors.count(true)),
169  m_roundSamples(ConfigurationHelper::getString(params, prefix + "roundSamples", "round.sam")),
170  m_smallSamples(ConfigurationHelper::getString(params, prefix + "smallSamples", "small.sam")),
171  m_wallSamples(ConfigurationHelper::getString(params, prefix + "wallSamples", "wall.sam"))
172 {
173  if (m_activeSensors.size() != 8) {
174  ConfigurationHelper::throwUserConfigError(prefix + "activeSensors", params.getValue(prefix + "activeSensors"), "The parameter must be a list of exactly 8 elements either equal to 1 or to 0 (do not use any space to separate elements, just put them directly one after the other)");
175  }
176 
177  // Checking that the sampled files have the right number of IR sensors
178  if (m_roundSamples.numIR() != 8) {
179  ConfigurationHelper::throwUserConfigError(prefix + "roundSamples", m_roundSamples.filename(), "The file has samples for the wrong number of sensors, expected 8, got " + QString::number(m_roundSamples.numIR()));
180  }
181  if (m_smallSamples.numIR() != 8) {
182  ConfigurationHelper::throwUserConfigError(prefix + "smallSamples", m_smallSamples.filename(), "The file has samples for the wrong number of sensors, expected 8, got " + QString::number(m_smallSamples.numIR()));
183  }
184  if (m_wallSamples.numIR() != 8) {
185  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()));
186  }
187 
188  // Here we also need the arena to work
189  addUsableResource("arena");
190 }
191 
193 {
194  // Nothing to do here
195 }
196 
198 {
199  // Calling parent function
200  KheperaSensor::save(params, prefix);
201 
202  // Saving parameters
203  params.startObjectParameters(prefix, "KheperaSampledProximityIRSensor", this);
204  QString activeSensorsString;
205  for (int i = 0; i < m_activeSensors.size(); i++) {
206  activeSensorsString += (m_activeSensors[i] ? "1" : "0");
207  }
208  params.createParameter(prefix, "activeSensors", activeSensorsString);
209  params.createParameter(prefix, "roundSamples", m_roundSamples.filename());
210  params.createParameter(prefix, "smallSamples", m_smallSamples.filename());
211  params.createParameter(prefix, "wallSamples", m_wallSamples.filename());
212 }
213 
215 {
216  // Calling parent function
218 
219  // Describing our parameters
220  Descriptor d = addTypeDescription(type, "The sampled proximity infrared sensors of the Khepera", "This is the sampled version of the proximity infrared sensors of the Khepera. This sensor only works with objects created using the Arena");
221  d.describeString("activeSensors").def("11111111").help("Which IR sensors of the robot are actually enabled", "This is a string of exactly 8 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)");
222  d.describeString("roundSamples").def("round.sam").help("The name of the file with samples for big round objects");
223  d.describeString("smallSamples").def("small.sam").help("The name of the file with samples for small round objects");
224  d.describeString("wallSamples").def("wall.sam").help("The name of the file with samples for walls");
225 }
226 
228 {
229  // Checking all resources we need exist
231 
232  // Acquiring the lock to get resources
233  ResourcesLocker locker(this);
234 
235  // Getting the list of objects in the arena
236  const QVector<PhyObject2DWrapper*>& objectsList = m_arena->getObjects();
237 
238  // Preparing the vector with activations and setting all values to 0
239  QVector<real> activations(m_activeSensors.size(), 0.0);
240 
241  // Cycling through the list of objects. We first need to get the current position and orientation of the robot
242  //const wVector robotPos = m_robot->position();
243  //const real robotAng = m_robot->orientation(m_arena->getPlane());
244  foreach(const PhyObject2DWrapper* obj, objectsList) {
245  // Computing angle and distance. We don't need to remove the robot to which this sensor belongs because
246  // the calculatations will give a negative distance
247  double distance;
248  double angle;
249 
250  // If computeDistanceAndOrientationFromRobot returns false, we have to discard this object
251  if (!obj->computeDistanceAndOrientationFromRobot(*(m_arena->getRobotWrapper(m_kheperaResource)), distance, angle)) {
252  continue;
253  }
254 
255  // Getting the activation. The switch is to understand which samples to use
256  QVector<unsigned int>::const_iterator actIt = QVector<unsigned int>::const_iterator();
257  switch (obj->type()) {
258  case PhyObject2DWrapper::Wall:
259  actIt = m_wallSamples.getActivation(distance, angle);
260  break;
261  case PhyObject2DWrapper::SmallCylinder:
262  actIt = m_smallSamples.getActivation(distance, angle);
263  break;
264  case PhyObject2DWrapper::BigCylinder:
265  actIt = m_roundSamples.getActivation(distance, angle);
266  break;
267  case PhyObject2DWrapper::WheeledRobot:
268  actIt = m_roundSamples.getActivation(distance, angle);
269  break;
270  default:
271  //Logger::warning("The sampled infrared sensor only works with Small Cylinders, Big Cylinders, Walls and other Robots");
272  continue;
273  }
274 
275  // Adding activations in the activations vector
276  for (int i = 0; i < activations.size(); ++i, ++actIt) {
277  activations[i] = min(1.0, activations[i] + (real(*actIt) / 1024.0));
278  }
279  }
280 
281  // Finally activating neurons
282  m_neuronsIterator->setCurrentBlock(name());
283  for (int i = 0; i < m_activeSensors.size(); i++) {
284  if (m_activeSensors[i]) {
285  m_neuronsIterator->setInput(applyNoise(activations[i], 0.0, 1.0));
286  m_neuronsIterator->nextNeuron();
287  }
288  }
289 }
290 
292 {
293  return m_numActiveSensors;
294 }
295 
296 void KheperaSampledProximityIRSensor::resourceChanged(QString resourceName, ResourceChangeType changeType)
297 {
298  // Calling parent function
299  KheperaSensor::resourceChanged(resourceName, changeType);
300 
301  if (changeType == Deleted) {
302  return;
303  }
304 
305  if (resourceName == m_kheperaResource) {
306  m_robot = getResource<Khepera>();
307 
308  // Disabling proximity IR sensors, they are not used here
309  m_robot->proximityIRSensorController()->setEnabled(false);
310  } else if (resourceName == m_neuronsIteratorResource) {
311  m_neuronsIterator = getResource<NeuronsIterator>();
312  m_neuronsIterator->setCurrentBlock(name());
313 
314  // We use the actual sensor ID in the neuron name
315  for (int i = 0; i < m_activeSensors.size(); i++) {
316  if (m_activeSensors[i]) {
317  m_neuronsIterator->setGraphicProperties("ir" + QString::number(i), 0.0, 1.0, Qt::red);
318  m_neuronsIterator->nextNeuron();
319  }
320  }
321  } else if (resourceName == "arena") {
322  // Storing the pointer to the arena
323  m_arena = getResource<Arena>();
324  } else {
325  Logger::info("Unknown resource " + resourceName + " for " + name());
326  }
327 }
328 
330  KheperaSensor(params, prefix),
331  m_robot(NULL),
332  m_arena(NULL),
333  m_neuronsIterator(NULL),
334  m_activeSensors(ConfigurationHelper::getBoolVector(params, prefix + "activeSensors", "11111111")),
335  m_numActiveSensors(m_activeSensors.count(true)),
336  m_lightSamples(ConfigurationHelper::getString(params, prefix + "lightSamples", "light.sam"))
337 {
338  if (m_activeSensors.size() != 8) {
339  ConfigurationHelper::throwUserConfigError(prefix + "activeSensors", params.getValue(prefix + "activeSensors"), "The parameter must be a list of exactly 8 elements either equal to 1 or to 0 (do not use any space to separate elements, just put them directly one after the other)");
340  }
341 
342  // Checking that the sampled files have the right number of IR sensors
343  if (m_lightSamples.numIR() != 8) {
344  ConfigurationHelper::throwUserConfigError(prefix + "lightSamples", m_lightSamples.filename(), "The file has samples for the wrong number of sensors, expected 8, got " + QString::number(m_lightSamples.numIR()));
345  }
346 
347  // Here we also need the arena to work
348  addUsableResource("arena");
349 }
350 
352 {
353  // Nothing to do here
354 }
355 
357 {
358  // Calling parent function
359  KheperaSensor::save(params, prefix);
360 
361  // Saving parameters
362  params.startObjectParameters(prefix, "KheperaSampledLightSensor", this);
363  QString activeSensorsString;
364  for (int i = 0; i < m_activeSensors.size(); i++) {
365  activeSensorsString += (m_activeSensors[i] ? "1" : "0");
366  }
367  params.createParameter(prefix, "activeSensors", activeSensorsString);
368  params.createParameter(prefix, "lightSamples", m_lightSamples.filename());
369 }
370 
372 {
373  // Calling parent function
375 
376  // Describing our parameters
377  Descriptor d = addTypeDescription(type, "The sampled light sensors of the Khepera", "This is the sampled version of the light sensors of the Khepera. This sensor only works with objects created using the Arena");
378  d.describeString("activeSensors").def("11111111").help("Which light sensors of the robot are actually enabled", "This is a string of exactly 8 elements. Each element can be either \"0\" or \"1\" to respectively disable/enable the corresponding light 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)");
379  d.describeString("lightSamples").def("light.sam").help("The name of the file with samples for light sensors");
380 }
381 
383 {
384  // Checking all resources we need exist
386 
387  // Acquiring the lock to get resources
388  ResourcesLocker locker(this);
389 
390  // Getting the list of objects in the arena
391  const QVector<PhyObject2DWrapper*>& objectsList = m_arena->getObjects();
392 
393  // Preparing the vector with activations and setting all values to 0
394  QVector<real> activations(m_activeSensors.size(), 0.0);
395 
396  // Cycling through the list of objects. We first need to get the current position and orientation of the robot
397  //const wVector robotPos = m_robot->position();
398  //const real robotAng = m_robot->orientation(m_arena->getPlane());
399  foreach(const PhyObject2DWrapper* obj, objectsList) {
400  // If the object is not a LightBulb, discarding it
401  if (obj->type() != PhyObject2DWrapper::LightBulb) {
402  continue;
403  }
404 
405  // Computing angle and distance
406  double distance;
407  double angle;
408 
409  // If computeDistanceAndOrientationFromRobot returns false, we have to discard this object
410  if (!obj->computeDistanceAndOrientationFromRobot(*(m_arena->getRobotWrapper(m_kheperaResource)), distance, angle)) {
411  continue;
412  }
413 
414  // Getting the activation (we already checked that the object is a LightBulb)
415  QVector<unsigned int>::const_iterator actIt = m_lightSamples.getActivation(distance, angle);
416 
417  // Adding activations in the activations vector
418  for (int i = 0; i < activations.size(); ++i, ++actIt) {
419  activations[i] = min(1.0, activations[i] + (real(*actIt) / 1024.0));
420  }
421  }
422 
423  // Finally activating neurons
424  m_neuronsIterator->setCurrentBlock(name());
425  for (int i = 0; i < m_activeSensors.size(); i++) {
426  if (m_activeSensors[i]) {
427  m_neuronsIterator->setInput(applyNoise(activations[i], 0.0, 1.0));
428  m_neuronsIterator->nextNeuron();
429  }
430  }
431 }
432 
434 {
435  return m_numActiveSensors;
436 }
437 
438 void KheperaSampledLightSensor::resourceChanged(QString resourceName, ResourceChangeType changeType)
439 {
440  // Calling parent function
441  KheperaSensor::resourceChanged(resourceName, changeType);
442 
443  if (changeType == Deleted) {
444  return;
445  }
446 
447  if (resourceName == m_kheperaResource) {
448  m_robot = getResource<Khepera>();
449  } else if (resourceName == m_neuronsIteratorResource) {
450  m_neuronsIterator = getResource<NeuronsIterator>();
451  m_neuronsIterator->setCurrentBlock(name());
452 
453  // We use the actual sensor ID in the neuron name
454  for (int i = 0; i < m_activeSensors.size(); i++) {
455  if (m_activeSensors[i]) {
456  m_neuronsIterator->setGraphicProperties("l" + QString::number(i), 0.0, 1.0, Qt::red);
457  m_neuronsIterator->nextNeuron();
458  }
459  }
460  } else if (resourceName == "arena") {
461  // Storing the pointer to the arena
462  m_arena = getResource<Arena>();
463  } else {
464  Logger::info("Unknown resource " + resourceName + " for " + name());
465  }
466 }
467 
469  KheperaSensor(params, prefix),
470  m_robot(NULL),
471  m_arena(NULL),
472  m_neuronsIterator(NULL)
473 
474 {
475  // Here we also need the arena to work
476  addUsableResource("arena");
477 }
478 
480 {
481  // Nothing to do here
482 }
483 
485 {
486  // Calling parent function
487  KheperaSensor::save(params, prefix);
488 
489  // Saving parameters
490  params.startObjectParameters(prefix, "KheperaGroundSensor", this);
491 
492 }
493 
495 {
496  // Calling parent function
498 
499  // Describing our parameters
500  Descriptor d = addTypeDescription(type, "The ground sensor of the khepera robot", "The ground sensors of the khepera robot. It is an infrared sensor that can be mounted on the bottom part of the robot.");
501 }
502 
504 {
505  // Checking all resources we need exist
507 
508  // Acquiring the lock to get resources
509  ResourcesLocker locker(this);
510 
511  // Getting the color under the robot
512  const QColor color = getColorAtArenaGroundPosition(m_arena, m_robot->position());
513  const real actv = 1.0 - real(qGray(color.rgb())) / 255.0;
514 
515  // Finally activating neurons
516  m_neuronsIterator->setCurrentBlock(name());
517  for (int i = 0; i < size(); i++) {
518  m_neuronsIterator->setInput(applyNoise(actv, 0.0, 1.0));
519  m_neuronsIterator->nextNeuron();
520  }
521 }
522 
524 {
525  return 1;
526 }
527 
528 void KheperaGroundSensor::resourceChanged(QString resourceName, ResourceChangeType changeType)
529 {
530  // Calling parent function
531  KheperaSensor::resourceChanged(resourceName, changeType);
532 
533  if (changeType == Deleted) {
534  return;
535  }
536 
537  if (resourceName == m_kheperaResource) {
538  m_robot = getResource<Khepera>();
539 
540 
541  } else if (resourceName == m_neuronsIteratorResource) {
542  m_neuronsIterator = getResource<NeuronsIterator>();
543  m_neuronsIterator->setCurrentBlock(name());
544 
545  // We use the actual sensor ID in the neuron name
546  for (int i = 0; i < size(); i++) {
547  m_neuronsIterator->setGraphicProperties("g" + QString::number(i), 0.0, 1.0, Qt::red);
548  m_neuronsIterator->nextNeuron();
549  }
550  } else if (resourceName == "arena") {
551  // Storing the pointer to the arena
552  m_arena = getResource<Arena>();
553  } else {
554  Logger::info("Unknown resource " + resourceName + " for " + name());
555  }
556 }
557 
559 {
560  switch (mode) {
561  case AbsoluteMode:
562  return "Absolute";
563  case DeltaMode:
564  return "Delta";
565  default:
566  return "Unknown";
567  }
568 
569  return "UnknownMode";
570 
571 }
572 
574 {
575  mode = mode.toUpper();
576 
577  if (mode == "ABSOLUTE") {
578  return AbsoluteMode;
579  } else if (mode == "DELTA") {
580  return DeltaMode;
581  } else {
582  return UnknownMode;
583  }
584 
585  return UnknownMode;
586 }
587 
589  KheperaSensor(params, prefix),
590  m_robot(NULL),
591  m_neuronsIterator(NULL),
592  m_mode(stringToMode(ConfigurationHelper::getString(params, prefix + "mode", "Absolute")))
593 {
594  if (m_mode == UnknownMode) {
595  ConfigurationHelper::throwUserConfigError(prefix + "mode", params.getValue(prefix + "mode"), "The parameter must be one of \"Absolute\" or \"Delta\" (case insensitive)");
596  }
597 }
598 
600 {
601  // Nothing to do here
602 }
603 
605 {
606  // Calling parent function
607  KheperaSensor::save(params, prefix);
608 
609  // Saving parameters
610  params.startObjectParameters(prefix, "KheperaWheelSpeedsSensor", this);
611  params.createParameter(prefix, "mode", modeToString(m_mode));
612 }
613 
615 {
616  // Calling parent function
618 
619  // Describing our parameters
620  Descriptor d = addTypeDescription(type, "The sensor reporting the actual velocity of the wheels of the Khepera", "This sensor have three modalities, see the mode parameter");
621  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\"");
622 }
623 
625 {
626  // Checking all resources we need exist
628 
629  // Acquiring the lock to get resources
630  ResourcesLocker locker(this);
631 
632  // Getting the motor controller for the attachment device
633  const WheelMotorController *const ctrl = m_robot->wheelsController();
634 
635  // Setting the current block to update the input neurons
636  m_neuronsIterator->setCurrentBlock(name());
637 
638  // Now reading values of the current and desired velocity
639  double curVel1;
640  double curVel2;
641  double desVel1;
642  double desVel2;
643  double minSpeed1;
644  double minSpeed2;
645  double maxSpeed1;
646  double maxSpeed2;
647  ctrl->getSpeeds(curVel1, curVel2);
648  ctrl->getDesiredSpeeds(desVel1, desVel2);
649  ctrl->getSpeedLimits(minSpeed1, minSpeed2, maxSpeed1, maxSpeed2);
650  double nCurVel1 = linearMap(curVel1, minSpeed1, maxSpeed1, -1.0, 1.0);
651  double nCurVel2 = linearMap(curVel2, minSpeed2, maxSpeed2, -1.0, 1.0);
652  double nDesVel1 = linearMap(desVel1, minSpeed1, maxSpeed1, -1.0, 1.0);
653  double nDesVel2 = linearMap(desVel2, minSpeed2, maxSpeed2, -1.0, 1.0);
654  switch (m_mode) {
655  case AbsoluteMode:
656  m_neuronsIterator->setInput(applyNoise(nCurVel1, -1.0, 1.0));
657  m_neuronsIterator->nextNeuron();
658  m_neuronsIterator->setInput(applyNoise(nCurVel2, -1.0, 1.0));
659  m_neuronsIterator->nextNeuron();
660  break;
661  case DeltaMode:
662  m_neuronsIterator->setInput(applyNoise(min(1.0, fabs(nDesVel1 - nCurVel1)), 0.0, 1.0));
663  m_neuronsIterator->nextNeuron();
664  m_neuronsIterator->setInput(applyNoise(min(1.0, fabs(nDesVel2 - nCurVel2)), 0.0, 1.0));
665  m_neuronsIterator->nextNeuron();
666  break;
667  default:
668  // We should never get here
669  throwUserRuntimeError("Invalid mode for KheperaWheelSpeedsSensor");
670  break;
671  }
672 }
673 
675 {
676  return 2;
677 }
678 
679 void KheperaWheelSpeedsSensor::resourceChanged(QString resourceName, ResourceChangeType changeType)
680 {
681  // Calling parent function
682  KheperaSensor::resourceChanged(resourceName, changeType);
683 
684  if (changeType == Deleted) {
685  return;
686  }
687 
688  if (resourceName == m_kheperaResource) {
689  m_robot = getResource<PhyKhepera>();
690 
691  } else if (resourceName == m_neuronsIteratorResource) {
692  m_neuronsIterator = getResource<NeuronsIterator>();
693  m_neuronsIterator->setCurrentBlock(name());
694 
695  // Creating labels
696  real minNeuronValue = 0.0;
697  real maxNeuronValue = 1.0;
698  switch (m_mode) {
699  case AbsoluteMode:
700  minNeuronValue = -1.0;
701  maxNeuronValue = 1.0;
702  break;
703  case DeltaMode:
704  minNeuronValue = 0.0;
705  maxNeuronValue = 1.0;
706  break;
707  default:
708  // We should never get here
709  minNeuronValue = 0.0;
710  maxNeuronValue = 1.0;
711  break;
712  }
713  m_neuronsIterator->setGraphicProperties("w0", minNeuronValue, maxNeuronValue, Qt::red);
714  m_neuronsIterator->nextNeuron();
715  m_neuronsIterator->setGraphicProperties("w1", minNeuronValue, maxNeuronValue, Qt::red);
716  m_neuronsIterator->nextNeuron();
717  } else {
718  Logger::info("Unknown resource " + resourceName + " for " + name());
719  }
720 }
721 
722 }
virtual void save(ConfigurationParameters &params, QString prefix)
Saves current parameters into the given ConfigurationParameters object.
void usableResources(QStringList resources)
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)
virtual ~KheperaSampledProximityIRSensor()
Destructor.
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.
QString m_neuronsIteratorResource
The name of th resource associated with the neural network iterator.
QString actualResourceNameForMultirobot(QString resourceName) const
Returns the actual resource name to use.
static QString getString(ConfigurationParameters &params, QString paramPath, QString def=QString())
void addUsableResource(QString resource)
virtual ~KheperaGroundSensor()
Destructor.
virtual void save(ConfigurationParameters &params, QString prefix)
Saves current parameters into the given ConfigurationParameters object.
QString name()
Return the name of the Sensor.
SimulatedIRProximitySensorController * proximityIRSensorController()
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.
KheperaGroundSensor(ConfigurationParameters &params, QString prefix)
Constructor.
virtual bool nextNeuron()=0
Go to the next neuron of the current block.
The base abstract class for khepera sensors.
virtual bool setCurrentBlock(QString blockName)=0
Set the current blocks of neurons to iterate.
virtual ~KheperaSensor()
Destructor.
static void describe(QString type)
Generates a description of this class and its parameters.
WheelMotorController * wheelsController()
static void describe(QString type)
Describe all the parameter for configuring the Sensor.
virtual void resourceChanged(QString name, ResourceChangeType changeType)
static void throwUserConfigError(QString paramName, QString paramValue, QString description)
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 QVector< PhyObject2DWrapper * > & getObjects() const
Returns the list of 2D objects.
Definition: arena.h:136
The base abstract class for the Sensor hierarchy.
static QString modeToString(Mode mode)
Returns the string representation of the given modality.
unsigned int numIR() const
Returns the number of IR sensors as read from the file.
Definition: sensors.h:879
KheperaSensor(ConfigurationParameters &params, QString prefix)
Constructor.
void getSpeeds(QVector< double > &speeds) const
Mode
The enum of different modalities for this sensor.
static Mode stringToMode(QString mode)
Converts the given string to a modality.
virtual ~KheperaSampledLightSensor()
Destructor.
void FARSA_UTIL_TEMPLATE throwUserRuntimeError(QString reason)
void getSpeedLimits(QVector< double > &minSpeeds, QVector< double > &maxSpeeds) const
virtual void update()
Performs the sensor update. This also modifies the activation of input neurons.
static void info(QString msg)
QString m_kheperaResource
The name of the resource associated with the e-puck robot.
A class wrapping a PhyObject to add methods suitable for wheeled robots simulations.
void resetNeededResourcesCheck()
Resets the check on needed resources so that the next call to checkAllNeededResourcesExist() will per...
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.
static void describe(QString type)
Generates a description of this class and its parameters.
bool startObjectParameters(QString groupPath, QString typeName, ParameterSettable *object)
void getDesiredSpeeds(QVector< double > &speeds) const
virtual void update()
Performs the sensor update. This also modifies the activation of input neurons.
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
float real
virtual ~KheperaProximityIRSensor()
Destructor.
virtual void update()
Performs the sensor update. This also modifies the activation of input neurons.
virtual void setInput(double value)=0
Set the input of the current neuron.
virtual void save(ConfigurationParameters &params, QString prefix)
Saves current parameters into the given ConfigurationParameters object.
KheperaProximityIRSensor(ConfigurationParameters &params, QString prefix)
Constructor.
KheperaWheelSpeedsSensor(ConfigurationParameters &params, QString prefix)
Constructor.
virtual int size()
Returns the number of neurons required by this sensor.
static void describe(QString type)
Describes all the parameters for this sensor.
FARSA_UTIL_TEMPLATE const T min(const T &t1, const U &t2)
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.
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) ...
double activation(int i) const
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.
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...
static void describe(QString type)
Generates a description of this class and its parameters.
KheperaSampledProximityIRSensor(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 createParameter(QString groupPath, QString parameter)
const QString & filename() const
Returns the name of the file from which samples are loaded.
Definition: sensors.h:869
virtual void save(ConfigurationParameters &params, QString prefix)
Saves the parameters of the sensor into the ConfigurationParameters object.
KheperaSampledLightSensor(ConfigurationParameters &params, QString prefix)
Constructor.
virtual wVector position() const
Returns the position of the robot.
Definition: robots.cpp:428
virtual void resourceChanged(QString resourceName, ResourceChangeType changeType)
The function called when a resource used here is changed.
virtual ~KheperaWheelSpeedsSensor()
Destructor.