diff --git a/doc/python/doxygen.hh b/doc/python/doxygen.hh
index b8c533c8ac3ba31a65d22055ee6fdd771e28ed0a..20a0bb3e25c889f5527767e3d4d5f6ffa33eeab2 100644
--- a/doc/python/doxygen.hh
+++ b/doc/python/doxygen.hh
@@ -17,6 +17,10 @@ static inline const char* run ()
 {
   return "";
 }
+static inline const char* attribute (const char*)
+{
+  return "";
+}
 };
 
 template <typename _class>
@@ -25,6 +29,12 @@ inline const char* class_doc ()
   return class_doc_impl<_class>::run();
 }
 
+template <typename _class>
+inline const char* class_attrib_doc (const char* name)
+{
+  return class_doc_impl<_class>::attribute(name);
+}
+
 template <typename FuncPtr>
 inline const char* member_func_doc (FuncPtr)
 {
diff --git a/doc/python/doxygen_xml_parser.py b/doc/python/doxygen_xml_parser.py
index 09fab28d0eca8cef251911232fc7e75012028bb5..448d6a271f013712373f62569993ee0dcf9f6c5e 100755
--- a/doc/python/doxygen_xml_parser.py
+++ b/doc/python/doxygen_xml_parser.py
@@ -26,7 +26,16 @@ static inline const char* run ()
 {{
   return "{docstring}";
 }}
+static inline const char* attribute (const char* attrib)
+{{{attributes}
+  (void)attrib; // turn off unused parameter warning.
+  return "";
+}}
 }};"""
+template_class_attribute_body = \
+"""
+  if (strcmp(attrib, "{attribute}") == 0)
+    return "{docstring}";"""
 template_constructor_doc = \
 """
 template <{tplargs}>
@@ -352,11 +361,23 @@ class ClassCompound (CompoundBase):
                 self.definition.find('briefdescription'),
                 self.definition.find('detaileddescription'),
                 self.index.output)
-        if len(docstring) == 0: return
+        attribute_docstrings = ""
+        for member in self.attributes:
+            _dc = self.index.xml_docstring.getDocString(
+                member.find('briefdescription'),
+                member.find('detaileddescription'),
+                self.index.output)
+            if len(_dc) == 0: continue
+            attribute_docstrings += template_class_attribute_body.format (
+                    attribute = member.find('name').text,
+                    docstring = _dc,
+                    )
+        if len(docstring) == 0 and len(attribute_docstrings) == 0: return
         output.out (template_class_doc.format (
             tplargs = self._templateDecl(),
             classname = self._className(),
             docstring = docstring,
+            attributes = attribute_docstrings,
             ))
 
     def write (self, output):
diff --git a/python/collision-geometries.cc b/python/collision-geometries.cc
index 77d614339a6368d2cde2b9fc25f5a3c3e20f00d6..5494cbf156ba98016ad028e2f8368cb6fdfb40c8 100644
--- a/python/collision-geometries.cc
+++ b/python/collision-geometries.cc
@@ -173,8 +173,8 @@ void exposeShapes ()
     ;
 
   class_ <Sphere, bases<ShapeBase>, shared_ptr<Sphere> >
-    ("Sphere", doxygen::class_doc<Sphere>(), init<FCL_REAL>())
-    .def_readwrite ("radius", &Sphere::radius)
+    ("Sphere", doxygen::class_doc<Sphere>(), init<FCL_REAL>(doxygen::constructor_doc<Sphere>()))
+    .def_readwrite ("radius", &Sphere::radius, doxygen::class_attrib_doc<Sphere>("radius"))
     ;
 
   class_ <TriangleP, bases<ShapeBase>, shared_ptr<TriangleP> >