[Programming C++] From shared_ptr to shared_ptr maintaining the use_count

Sometimes we need to store shared data pointers in an anoymous shared pointer shared_ptr<void>. The problem is when you want to convert back the shared_ptr<void> to shared_ptr<T> again. A priori, it is not possible, but we can do some tricks to solve this issue. Neddless to say that the first solution is – of course –  NOT USE shared_ptr<void>. Try to use boost::any or boost::variant objects in your problem. But still, if there may be some strange cases where it can be interesting the use of  anonymous shared_ptrs

The most you can until the momment is getting the original data is using the shared_ptr<void>::get() method to get the void* pointer. However you must maintain the shared_ptr<void> alive if you want to avoid the segmentation fault. The following test would FAIL in the last line:

TEST(basic_test, original_from_shared_void_to_t)
{
std::shared_ptr<A> a(new A);
std::shared_ptr<void> b =a;

ASSERT_TRUE(a.use_count()==2);
ASSERT_TRUE(b.use_count()==2);

 

a=std::shared_ptr<A>();
ASSERT_TRUE(a.use_count()==0);
ASSERT_TRUE(b.use_count()==1);

 

printf(“Testing access memory…\n”);
A* data=(A*)b.get();
data->foo(); //you can access to the fields and methods
//OK by the moment..

b=std::shared_ptr<void>();
ASSERT_TRUE(b.use_count()==0);

 

//and now crash because memory has been freed…

data->foo(); //segmentation fault
}

Do you have any idea? Perhaps you are thinking in this one (but it does not work):

std::shared_ptr<A> data= std::shared_ptr<A>((A*)b.get());
data->foo(); //it works because b still references it

//but the problem is the next fact
ASSERT_TRUE(b.use_count()==1);
ASSERT_TRUE(data.use_count()==1);
//both have different counts, they both should be 2 instead 1
//so here comes the crash…

b=std::shared_ptr<void>();
//the destructor is called
data->foo();

lesson lernt: you have to maintain b (or a copy of it) alive while the new pointer “data” is alive.

How to do it without think about it continuing working as always? The  solution is the “__magic_reinterpret_pointer_cast”. see the code:

template<typename T>
std::shared_ptr<T> __magic_reinterpret_pointer_cast(std::shared_ptr<void> b)
{
return std::shared_ptr<T>((T*)b.get(),[b](T* x){});
}

Whit it you can go back to your type shared_ptr<A> from shared_ptr<void> avoiding any segmentation fault. The trick is store a reference of the shared_ptr<void> inside the new shared_ptr<A>. Observe that there will be different “use counts” groups, so the use_count method is not reliable anymore. Appart from this everything look work well: See this example and please make me know other limitations on the approach if you notice it.

NOTE: Be careful because it has the same limitations to the reinterpet_cast. ¡¡This is not valid to cast to base or derived types!!. TEST(basic_test,t1)

TEST(basic_test, original_from_shared_void_to_t_reintrepret_cast)

{
std::shared_ptr<A> a(new A);
std::shared_ptr<void> b=a;

ASSERT_TRUE(a.use_count()==2);
ASSERT_TRUE(b.use_count()==2);

//removing one instance
b=std::shared_ptr<void>();
ASSERT_TRUE(a.use_count()==1);
ASSERT_TRUE(b.use_count()==0);

//restoring it again
b=a;

ASSERT_TRUE(a.use_count()==2);
ASSERT_TRUE(b.use_count()==2);
{
//”make magic trick
std::shared_ptr<A> c=__magic_reinterpret_pointer_cast<A>(b);

ASSERT_TRUE(a.use_count()==3);
ASSERT_TRUE(b.use_count()==3);
ASSERT_TRUE(c.use_count()==1); // THIS IS THE WARNING POINT

c=std::shared_ptr<A>();
ASSERT_TRUE(a.use_count()==2);
ASSERT_TRUE(b.use_count()==2);
}

{
//”make magic trick
std::shared_ptr<A> c=__magic_reinterpret_pointer_cast<A>(b);

ASSERT_TRUE(a.use_count()==3);
ASSERT_TRUE(b.use_count()==3);
ASSERT_TRUE(c.use_count()==1); // THIS IS THE WARNING POINT

a=std::shared_ptr<A>();
b=std::shared_ptr<void>();

ASSERT_TRUE(a.use_count()==0);
ASSERT_TRUE(b.use_count()==0);
ASSERT_TRUE(c.use_count()==1); // VOILA, STILL 1!
}
}

 

Quick logistic function with python and scipy

Basic example about how to make work the logistic function (or whichever else in scipy). It may be interesting to remember.

> ipython -pylab

import scipy
import scipy.stats
d=scipy.stats.logistic(1,loc=0.5,scale=0.5)
(x,y)=map(list, zip(*[ (i,d.cdf(i)) for i in numpy.arange(-1.0,1.0,0.01)]))
plot(x,y)

Eclipse CDT – Memory Heap limit

Para los sufridores del indexador de autocompletado de eclipse CDT: Ya sabréis que eclipse acaba cascando cuando intentade indexar unos cuantos de directorios de headers. Se puede solucionar facilmente aumentando la cantidad de memoria virtual posible que puede utilizar la jvm que hospeda al proceso eclipse.

Si tenéis la versión bundle ejecutar directamente:

./eclipse -vmargs -XX:MaxPermSize=600m

Mano de santo.

References:
http://help.eclipse.org/helios/index.jsp?topic=%2Forg.eclipse.platform.doc.user%2Ftasks%2Frunning_eclipse.htm

Interesting Survey about different Robotic Software Frameworks for Distributed Robotics

This work identifies many aspects of the distributed robotics and compare ROS and other Robotic Frameworks for distributed robotics. Here I show the abstract:

Abstract

Robotics is an area of research in which the paradigm of Multi-Agent Systems (MAS) can prove to be highly useful. Multi-Agent Systems come in the form of cooperative robots in a team, sensor networks based on mobile robots, and robots in Intelligent Environments, to name but a few. However, the development of Multi-Agent Robotic Systems (MARS) still presents major challenges. Over the past decade, a high number of Robotics Software Frameworks (RSFs) have appeared which propose some solutions to the most recurrent problems in robotics. Some of these frameworks, such as ROS, YARP, OROCOS, ORCA, Open-RTM, and Open-RDK, possess certain characteristics and provide the basic infrastructure necessary for the development of MARS. The contribution of this work is the identification of such characteristics as well as the analysis of these frameworks in comparison with the general-purpose Multi-Agent System Frameworks (MASFs), such as JADE and Mobile-C.

Keywords

  • Robotics;
  • MAS;
  • Agents;
  • Software frameworks;
  • Middleware;
  • Architecture

Cambiando el marco de referencia de una distribución Gaussiana

El trabajo de funciones probabilísticas gausianas en el espacio es algo muy habitual en robótica. Este tipo de distribuciones permite expresar una posición o pose (por ejemplo de un objeto u objetivo) de la cual se tiene cierta incertidumbre. Desde mi punto de vista se trata de una temática bastante interesante y me está permitiendo profundizar en algunos conceptos matemáticos como autovalores, números complejos y quaterniones. Otros posts previos que realicé en el pasado con temáticas relacionadas son:

Una función gausiana está compuesta de su vector media \mu y su matriz de covarianza \Sigma y se denota como P(x)\sim\mathcal{N}(\mu,\Sigma). El problema consiste en modificar estos parámetros para pasar del marco de referencia F_{A} al marco de referencia F_{B}. Estos marcos de referencia están descritos por una transformación lineal que incluye rotación y translación respecto a un marco de referencia universal, de modo que:

F_{A}\equiv(R_{A},T_{A})

F_{B}\equiv(R_{B},T_{B})

Cambio del marco de referencia del vector media \mu

El cambio de referencia del vector media es trivial dada una transformación TF entre marcos de referencia básicamente consiste en aplicar la transformación lineal al vector \mu_{A}:

\mu_{B} = R \mu_{A} + T

Donde:

R=R_{B}R_{A}^{-1}
T=T_{B}-R_{B}T_{A}

De echo en ocasiones los valores universales de los marcos de referencia R_{A}, T_{A}, R_{B}  y T_{B} no son conocidos, sino que directamente la relación entre ambos marcos TF\equiv (R,T).

Cambio del marco de referencia de la matriz de Covarianza \Sigma

¿Pero que pasa con la matriz de covarianza? En el caso de un problema unidimensional, el cambio de referencia del origen de coordenadas no afectaría a la matriz de covarianza \Sigma=\begin{bmatrix} \sigma^{2} \end{bmatrix} (que es la varianza). Por ejemplo: P(x)\sim\mathcal{N}(\mu_{A}=3,\Sigma_{A}=5) se convertiría en P(x)\sim\mathcal{N}(\mu_{B}=-7,\Sigma_{B}=5) si cambiaramos el origen de coordenadas desde el O=0 a O=10.

Para una función gausiana 2D o 3D es mucho más complicado. La matriz de covarianza representa la orientación de la distribución además de la  escala de la variabilidad en dentro de los ejes principales de esta rotación. A la derecha se muestra una figura de una función gausiana 2D. En una función gaussiana (creo, a ver si un matemático me lo confirma) que la probabilidad se extiende en N vectores ortogonales (autovectores) con diferentes escalas (autovalores) verificando que:

\Sigma = E (l I) E^{t}

Siendo l el vector de autovalores, el punto curioso es que la matriz E es una matriz de rotación cuyas columnas son los autovectores de \Sigma.  Es intuitivo ver que si el marco de referencia cambia, las coordenadas de estos autovectores cambiará, sin embargo la escala (autovalores) se mantendrá constante. Parece entonces sencillo.

Si estamos trabajando en el marco de referencia F_{A}F_{B} es conocido, entonces basta con cambiar el marco de referencia de los autovectores:

E_{B}=RE_{A}

\Sigma_{B}=RE_{A}(lI)(RE_{A})^{t}

o lo que es lo mismo si tenemos la información completa de F_{A}F_{B}:

\Sigma_{B}=R_{B}R_{A}^{-1}E_{A}(lI)(R_{B}R_{A}^{-1}E_{A})^{t}

Casos particulares que aún no se resolver

Sin embargo existen casos particulares y estos son los que a mi, personalmente me inquietan y aún no tengo claro como resolver:

  1. ¿Qué ocurre si la matriz de covarianza no es diagonalizable? Por ejemplo, se tiene total certeza de su posición en X, su posición en Y y algo de incertidumbre en Z. Siendo \Sigma_{A}=\begin{bmatrix}  0 & 0 & 0\\  0 & 0 & 0\\  0 & 0 & 2.3  \end{bmatrix} ¿Podría obtenerse la matriz E_{A} si solo tenemos un autovector?
  2. ¿Qué ocurre cuando trabajamos (en lugar de con un vector “posición” en 3D) con una “pose en el espacio” xyz+rpy 6D con una matriz de covarianza de 36 valores, donde se mezclan distintas unidades? Este tipo de representación gausiana es también muy utilizada en robótica, sin embargo, el abordaje del problema de cambio de sistema referencia de este tipo de distribuciones es algo que no he logrado localizar en ningún sitio. Parece un caso muy extraño dado que además los valores de rpy dependen en sí mismos del los ejes x,y,z del marco de referencia actual.
Ideas problema 1:
En el ejemplo tratado parece claro que el único autovector existente es v_0=\begin{vmatrix}\\ 0\\ 0\\ 1 \end{vmatrix} y su autovector \lambda_0=2.3 ya que verifica que \Sigma v_0 = \lambda v_0 . Intuyo que dada la precondición de ortogonalidad de los autovectores de la matriz E(¿inventado?) parece razonable que solo necesitamos un autovector para calcular E. De hecho  cualquier E que verifique que l=\begin{vmatrix}\\ \lambda_0\\ \lambda_1=0\\\lambda_2=0 \end{vmatrix} y sea ortogonal parece suficiente ¿sera correcto este razonamiento?Duda: Pienso que una matriz de covarianza no nula debería tener al menos un autovector real, pero de esto, no estoy seguro. Si fuera así, el problema estaría resuelto.
Ideas problema 2:
Creo que dado que el cambio de coordenadas en robótica solo afectaría a los ejes x, y y z el problema se simplificaría. El vector \mu para x, y y z cambiaría de la misma forma. Por el contrario los valores rpy en lugar de ser rotados serían trasladados. \mu_{B}= R* \mu_{A} + T donde:
R=\begin{bmatrix}  R_{xyz} & \O \\  \O & I\\\end{bmatrix}
y
T=\begin{bmatrix} t_x \\ t_y \\ t_z \\ getRoll(R) \\ getPitch(R) \\ getYaw(R) \\\end{bmatrix}
De esta forma las componentes de \Sigma_A definidas por covarianzas angulares, como \sigma_{row,pitch}=cov(row,pitch) permanecerían constantes tras la transformación TF, mientras que las componentes de la matríz como \sigma_{x,yaw}=cov(x,yaw) cambiarían su valor. Sin embargo, todo esto son por ahora solo intuiciones. ¿es correcto este razonamiento?¿Alguna ayuda?

Basic Rotations with Quaternions

The quaternions is a very interesting mathematical tools that make possible perform rotation operations without using rotation matrices. This method is efficent and secure (avoiding the gimbal lock effect) in dynamic situations. A very interesting explanation about the mathematical foundations and capacities of quaternions can be found here.

The ROS library TF provide several functions to handle quaternions in C++ and Python. There exists many opensource libraries which provides quaternion funciontalities like Eigen, Bullet to name a couple of them.

Rotating a point
ROS works with the right hand axis convention. This axis convention is specially adequate for mobile robots. Here the robot is always looking to the axis-x infinity.

import roslib
roslib.load_manifest('tf')
import tf
from tf.transformations import *

# we want to rotate the point using the x-axis ("roll")
rot=quaternion_from_euler(-numpy.pi/4,0,0)

# the object is located in the y=1. We use the format [x,y,z,w] and w is allways 0 for vectors
vec= [0,1,0,0]

#now we apply the mathematical operation res=q*v*q'. We use this function for multiplication but internally it is just a complex multiplication operation.
result=quaternion_multiply(quaternion_multiply(rot, vec),quaternion_conjugate(rot))

In [33]: result
Out[33]: array([ 0. , 0.70710678, -0.70710678, 0. ])

Concatenate Rotations
Here I show how to concatenate multiple rotations using quaternions:

q1=quaternion_from_euler(-numpy.pi/4,0,0)
q2=quaternion_from_euler(numpy.pi/4,0,0)
q3=quaternion_from_euler(-numpy.pi/4,0,0)
q4=quaternion_from_euler(numpy.pi/4,0,numpy.pi/4)

#the full transform is q4*q3*q2*q1
rot= quaternion_multiply(q4,quaternion_multiply(q3,quaternion_multiply(q2,q1)))
result=quaternion_multiply(quaternion_multiply(rot, vec),quaternion_conjugate(rot))

In [86]: result1
Out[86]: array([ 0. , 0.70710678, -0.70710678, 0. ])

In [90]: result2
Out[90]: array([ 0., 1., 0., 0.])

In [93]: result3
Out[93]: array([ 0. , 0.70710678, -0.70710678, 0. ])

In [96]: result
Out[96]: array([-0.70710678, 0.70710678, 0. , 0. ])

Basics Screens on linux

I always forge how to use the screen application in linux for ssh sesions. Here the basic stuff to work with screens:

Start
$ screen

Exit and close:
$$ CTRL + D
or
$$ exit

Disconect from the screen program but leaving it opened:
$$ CTRL +A CTRL+D

Reconect to an opened screen program:
$ screen -r

From the screen, create another “tab”:
$$ CTRL+A C

Switch selected tab:
$$ CTRL+A CTRL+A

List existing tabs:
$$ CTRL+A W

Vídeo Tutorial de Ros con Arduino

Ahí lo dejo para el que le pueda interesar como abordar la integración de ROS con arduino.

How to represent a 3D Gaussian Function with ROS rviz

The probabilistic functions are very usual in robotics to represent the certainty of states and observations. The most typical and used probabilistic function is the Gaussian function. Everybody who knows what is this immediately imagine a pretty bell which describes the samples nature.

In the one-dimensional case, a simple tuple (\mu, \sigma^{2}) mean, variance is enough information to imagine how the samples are behaving. This tuple can be also reinterpreted as an interval [\mu - \sigma^{2}, \mu + \sigma^{2}] where the samples most probably are located. For higher dimensions the \mu it is clear, but the equivalent element to describe the diversity, the covariance matrix \Sigma it is much lesser intuitive for most of people. The trick is imagine the ND gaussian bell as NDimensional ellipse. The shape and rotation of this ellipse is described by the covariance matrix. In this way the diversity of the distribution is intuitive.

It is extremely interesting to see and understand the relationship with the rotation and scale of the ellipsoid. If we define R as the rotation transform of the ellipsoid and l is a vector with the variances in the local frame of the ellipse (much easier to imagine) l = \begin{pmatrix}\sigma_{x_1,x_1}^{2} & ... & \sigma_{x_n,x_n}^{2}\end{pmatrix} , then the relationship between R, l and \Sigma is this:

\Sigma = R (l I) R^{t}

This have important implications because if you want to synthesizer a gaussian belief from a theoretical model can be hard imagine the covariance matrix values but it is very easy to think in an ellipse with a rotation and scale.

The inverse operation is also useful. For instance if you have a covariance matrix obtained experimentally and you wish to make a geometric interpretation of the distribution or just plot it, you can obtain the rotation matrix R and the scale vector l. Then the it is needed to compute the eigenvectors and eigenvalues. That is because:

R = eigvectors(\Sigma)
and
l = eigvalues(\Sigma)

Of course notice that if number of eigenVectors is lower than the dimensionality of the problem is because the ellipse is infinitely slim and as a consequence the determinant det \left | \Sigma \right | = 0 and then the matrix is singular. This means that one dimension should be removed if you want to compute likelihoods over that gaussian function.

Here I show how to represent a 3D gaussian function with ROS and rivz:

And here the code in python. Discussion about this subject in: http://answers.ros.org/question/2043/plot-a-gaussian-3d-representation-with-markers-in:

import roslib
roslib.load_manifest ("gaussian_markers")
import rospy
import PyKDL
from visualization_msgs.msg import Marker, MarkerArray
import visualization_msgs
from geometry_msgs.msg import Point
import numpy
from numpy import concatenate

#syntetic 3-D Gaussian probabilistic model for sampling
covMatModel =[[10, 10, 0],[10, 1, 0],[0, 0, 4]]
meanModel =[10, 10, 10]

#used to paint the autovectors
def markerVector(id,vector,position):
	marker = Marker ()
	marker.header.frame_id = "/root";
	marker.header.stamp = rospy.Time.now ()
	marker.ns = "my_namespace2";
	marker.id = id;
	marker.type = visualization_msgs.msg.Marker.ARROW
	marker.action = visualization_msgs.msg.Marker.ADD
	marker.scale.x=0.1
	marker.scale.y=0.3
	marker.scale.z=0.1
	marker.color.a= 1.0
	marker.color.r = 0.33*float(id)
	marker.color.g = 0.33*float(id)
	marker.color.b = 0.33*float(id)
	(start,end)=(Point(),Point())

	start.x = position[0]
	start.y = position[1]
	start.z = position[2]
	end.x=start.x+vector[0]
	end.y=start.y+vector[1]
	end.z=start.z+vector[2]

	marker.points.append(start)
	marker.points.append(end)
	print str(marker)
	return marker

rospy.init_node ('markersample', anonymous = True)
points_pub = rospy.Publisher ("visualization_markers", visualization_msgs.msg.Marker)
gauss_pub = rospy.Publisher ("gaussian", visualization_msgs.msg.Marker)

while not rospy.is_shutdown ():
	syntetic_samples = None

	#painting all the syntetic points
	for i in xrange (10, 5000):
		p = numpy.random.multivariate_normal (meanModel, covMatModel)
		if syntetic_samples == None:
			syntetic_samples =[p]
		else:
			syntetic_samples = concatenate ((syntetic_samples,[p]), axis = 0)

		marker = Marker ()
		marker.header.frame_id = "/root";
		marker.header.stamp = rospy.Time.now ()
		marker.ns = "my_namespace2";
		marker.id = i;
		marker.type = visualization_msgs.msg.Marker.SPHERE
		marker.action = visualization_msgs.msg.Marker.ADD
		marker.pose.position.x = p[0]
		marker.pose.position.y = p[1]
		marker.pose.position.z = p[2]
		marker.pose.orientation.x = 1
		marker.pose.orientation.y = 1
		marker.pose.orientation.z = 1
		marker.pose.orientation.w = 1
		marker.scale.x = 0.05
		marker.scale.y = 0.05
		marker.scale.z = 0.05
		marker.color.a = 1.0
		marker.color.r = 0.0
		marker.color.g = 0.0
		marker.color.b = 0.0
		points_pub.publish (marker)

	#calculating Gaussian parameters
	syntetic_samples = numpy.array (syntetic_samples)
	covMat = numpy.cov (numpy.transpose (syntetic_samples))
	mean = numpy.mean ([syntetic_samples[: , 0], syntetic_samples[: , 1], syntetic_samples[:, 2]], axis = 1)

	#painting the gaussian ellipsoid marker
	marker = Marker ()
	marker.header.frame_id ="/root";
	marker.header.stamp = rospy.Time.now ()
	marker.ns = "my_namespace";
	marker.id = 0;
	marker.type = visualization_msgs.msg.Marker.SPHERE
	marker.action = visualization_msgs.msg.Marker.ADD
	marker.pose.position.x = mean[0]
	marker.pose.position.y = mean[1]
	marker.pose.position.z = mean[2]

	#getting the distribution eigen vectors and values
	(eigValues,eigVectors) = numpy.linalg.eig (covMat)

	#painting the eigen vectors
	id=1
	for v in eigVectors:
		m=markerVector(id, v*eigValues[id-1], mean)
		id=id+1
		points_pub.publish(m)

	#building the rotation matrix
	eigx_n=PyKDL.Vector(eigVectors[0,0],eigVectors[0,1],eigVectors[0,2])
	eigy_n=-PyKDL.Vector(eigVectors[1,0],eigVectors[1,1],eigVectors[1,2])
	eigz_n=PyKDL.Vector(eigVectors[2,0],eigVectors[2,1],eigVectors[2,2])
	eigx_n.Normalize()
	eigy_n.Normalize()
	eigz_n.Normalize()
  	rot = PyKDL.Rotation (eigx_n,eigy_n,eigz_n)
	quat = rot.GetQuaternion ()

	#painting the Gaussian Ellipsoid Marker
	marker.pose.orientation.x =quat[0]
	marker.pose.orientation.y = quat[1]
	marker.pose.orientation.z = quat[2]
	marker.pose.orientation.w = quat[3]
	marker.scale.x = eigValues[0]*2
	marker.scale.y = eigValues[1]*2
	marker.scale.z =eigValues[2]*2

	marker.color.a = 0.5
	marker.color.r = 0.0
	marker.color.g = 1.0
	marker.color.b = 0.0

	gauss_pub.publish (marker)
	rospy.sleep (.5)

Libros para la introducción e investigación en Robótica

Como los que me conocéis sabéis, actualmente soy estudiante de Doctorado en el departamento ATC (Arquitectura y Tecnología de computadores) en E.T.S. Ingeniería Informática de Sevilla. La temática de mi tesis se ubica dentro del área de la robótica. Actualmente me encuentro en la fase de realización de la tesina (trabajo de investigación previo). Básicamente consiste en la realización de un estudio profundo del estado del arte , detectar carencias en las soluciones propuestas e introducir las líneas generales del trabajo de Tesis. Dentro de la robótica (por interés personal y por historia de la investigación en el departamento) me centro en las áreas de navegación, planificación, control compartido, sensores distribuidos y arquitecturas software robóticas.

Los artículos de investigación (Papers) son muy útiles para estar a la última, sin embargo la cantidad de papers que aparecen cada mes es desorbitarte, hay mucha información que no es relevante y en ocasiones es difícil discernir si las aportaciones son buenas, interesantes para tu investigación y merece la pena una profundización.

Sin embargo existe una fuente de información complementaria e igual o más importante que los papers: los libros. Los libros habitualmente están más atrasados que los papers, sin embargo, estos presentan innumerables cualidades: se profundiza mucho más en la temática, formato y notación unificada, aprendizaje progresivo, etc. Además, los libros ofrecen contenidos habitualmente más aceptados y reconocidos por la comunidad científica con una madurez media o alta. De esta forma se convierten en un pilar básico para la formación alrededor de los cuales debe girar el conocimiento adquirido en los artículos científicos (más efímeros y traicioneros). Aquí dejo una lista de los 4 libros (hay alguno más que me encantaron, pero estos son los principales) que para mí son sobresalientes y que están permitiéndome como estudiante de doctorado con vagos conocimientos previos en la robótica ir adquiriendo poco a poco destreza y experiencia como para poder aportar nuevas ideas.

Probabilistic Robotics – Año 2006. Un libro absolutamente imprescindible para comprender los enfoques probabilísticos que utiliza hoy día la robótica para aportar soluciones. Tiene una matemática dura, y todas las técnicas presentadas ofrecen su demostración matemática. En cualquier caso es un libro muy aplicable de manera casi directa en el software para robots. Se centra en las áreas de localización, construcción de mapas, modelos de sensores y modelos de movimiento de robots y planificación, todo desde un enfoque probabilístico. A pesar de explicar diversas técnicas exitosas en estas áreas el enfoque del libro no son estas sino más bien pretende ilustrar un punto de partida para enfocar los problemas robóticos de una forma mas realista y robusta haciendo uso de la estadística. Su principal autor Sebastian Thrun es hoy día una de las principales referencias mundiales en el área de la robótica.
Planning Algorithms – Año 2010. Este libro profundiza de forma exhaustiva en muchísimas técnicas y aspectos importantes en la planificación para robot. Se centra especialmente en la planificación de movimiento (aunque también trata temas de planificación de más alto nivel, tareas, etc). Es muy profundo, duro y formal matemáticamente. Más específicamente se centra en técnicas de planificación de movimiento global deterministas y basadas en muestras, planificación con restricciones kinodinámicas y no-holónomas, etc. Una de las principales ventajas de este libro es que está disponible online de forma gratuita, y además que es actualizado frecuentemente.
Springer Handbook of Robotics – La biblia de la robótica. Casi 1600 páginas de conocimiento. Bastante actualizado, finales del año 2008. Libro para ser utilizado como referencia para introducirse a cualquier temática de la robótica y encontrar fuentes. Trata de todos los temas: Fundamentos de la robótica (Cinemática, Dinámica, Mecánica, Control, Planificación, IA, Arquitecturas software), Estructuras de Robots, Sensores y percepción, manipulación, robótica distribuida, robótica de servicios, robótica en el ámbito de los seres humanos. El libro ha sido realizado por decenas de autores, especialistas en cada área. El nivel de formalismo y profundización varía según el capítulo y la madurez del tema. Otro libro muy recomendable para tener a mano.

Principles of Robot Motion – Este libro se centra en la planificación de movimiento. Es un libro cuya temática es muy parecida a Planning Algorithms, sin embargo es mucho mas ameno y sencillo de leer especialmente para los Ingenieros Informáticos (como yo) ya que presenta vocabulario y técnicas familiares del área de la IA. Realiza un estudio del arte (año 2005) en técnicas de planificación, centrándose en la planificación global (incluido sistemas con restricciones kinodinámicas). Toca también temas de cinemática, dinámica, técnicas de localización probabilísticas y SLAM.

Pues nada, ahí lo dejo, espero que pueda ayudar a cualquiera que esté iniciándose e investigando en este área. ¡Cualquier comentario, sugerencia u opiniones sobre estos u otros libros de robótica son bienvenidos!
Saludos. Bon apetit!