Reminds me of this post that came up on HN not too long ago:
Reminds me of this post that came up on HN not too long ago:
Rather than complaining about how everyone else is a bonehead for not using Lisp, write some libraries to make it useful for more things in the real world.
Also, Python does pretty well for real-time control. At Anybots we use it to run walking balance feedback loops at 100 Hz in the same process as a GUI and logging and it never misses a tick. PLT Scheme (used on HN) frequently pauses for 10+ seconds to GC. While there are theoretical concurrent GC systems for Lisp, none of them seem usable in real implementations.
Most of the 3D stuff is performance-critical, so I typically prototype in Python and then convert to C++, which for graphics code isn't too painful. The Boost.Python interface makes it pretty easy.
Also, the Cairo graphics interface is wonderful for drawing charts, animated robot stick figures, and many other visualizations. It has a full Postscript rendering model with alpha blending.
It looks like PLT Scheme has an OpenGL binding too, though I haven't seen it used. It looks very low-level, for instance it has separate methods named: gl.Vertex3d gl.Vertex3dv gl.Vertex3f gl.Vertex3fv gl.Vertex3i gl.Vertex3iv gl.Vertex3s gl.Vertex3sv
Also, if you haven't used it yet, check out Py++. It takes a lot of the pain out of hand-authoring a Boost.Python code file. I'm using Py++ to automatically generate Boost.Python bindings for the C++ library FCollada. (FCollada is a library for accessing 3D modeling data exported into the .dae COLLADA format.)
Thanks for the tip about Cairo.
Also, glVertex3d, 3dv, 3f, etc are part of the standard GL API. The 'd' suffix indicates 'double', 'f' indicates 'float', 'i' indicates 'int', 's' indicates 'short', and the 'v' suffix indicates that the function accepts a pointer rather than 3 separate components passed by value. Of course, the glVertex* API has been deprecated because VBOs are far more efficient.
Just curious again, why do you use OpenGL for Anybots? Do you create simulations before building new robot prototypes?
We use OpenGL to show real-time renderings of the robot, derived from the gyros and joint angle sensors. We have an analysis tool that shows, either in real time or post-run analysis, renderings synchronized with high-speed video of the robot and scrolling strip charts of every important variable over time. I always see much more looking at slow-motion videos & renderings afterwards than looking at the real robot.
OpenGL rendering also turned out to be useful for extracting data from CAD models. Our CAD software (SolidWorks) can export STL files (a list of polygons) and we need to extract center of mass and moment of inertia and such. Doing that without visualizing it is a nightmare.
We have done dynamics simulations (using ODE), but they haven't had much predictive value.
Are you computing center of mass / moment of inertia yourself, or using a 3rd party library to do it? PhysX is free, and I believe it can do those calculations for you fairly automatically. (In PhysX, a 'scene' is composed of 'actors', and each actor is described by a set of shape descriptors. A shape descriptor can represent a box, a sphere, a capsule, a convex hull, etc. So a laptop actor could crudely be approximated with two box shape descriptors (one for the screen, one for the body) connected by a joint. Given those shape descriptors, the library calculates the actor's center of mass / moment of inertia / etc. If your CAD software simply exports a list of polygons, you'll need to decompose those into a set of convex hulls using convex hull decomposition techniques: http://codesuppository.blogspot.com/2006/04/approximate-conv... ) You also might have better luck running dynamics simulations with PhysX than with ODE. It comes with a large number of code examples to get you started: http://developer.nvidia.com/object/physx_downloads.html
http://www.cs.berkeley.edu/~jfc/mirtich/massProps.html
Maybe 80 LOC. I'm not sure why anything more complex is needed.
PhysX does seem promising.
The other reason I mentioned convex hull computation is because PhysX can only simulate dynamic actors that are composed of boxes, spheres, capsules, and convex hulls, IIRC. Arbitrary polygon meshes aren't supported for dynamic actors, because they are very difficult to simulate in realtime. So if you wanted to use PhysX for dynamics simulations, you would probably need to decompose your model into a set of convex hulls.
Good luck -- if you need any assistance with PhysX, feel free to contact me at shawnpresser@gmail.com.
(I'm just brainstorming ideas in the rest of this post; I'm not sure whether they'll work, but it's a fun problem to think about.)
Perhaps it would be useful to write your own simulator that incorporates data about how the components of the robot behave in the real world, to get a more accurate simulation. By that I mean, the problem is that the robot model has so much complexity that it's difficult to simulate accurately. So instead of creating a mathematical model for how a compressed-air actuator behaves, for example, gather real-world data about how it actually behaves in the robot, then incorporate that data into the simulator. I mean, if the robot is walking slowly on a flat surface, then its individual components behave in the same ways each time the robot takes a step forward, right? Therefore it seems like the behavior of the whole robot can be reproduced and predicted in a simulator, since the behavior of each component is known (under controlled conditions, like when the robot is walking slowly). Brute force the problem by using large amounts of real-world data, is what I'm getting at.
"Brute force the problem by using large amounts of real-world data, is what I'm getting at."
Absolutely, that is Trevor's viewpoint, and I agree. Turns out to be somewhat difficult in practice. It's hard to even know what all the parameters should be, much less do all the work necessary to tune them. And all the while, the robot itself is changing. Joints get loose; servos get replaced. It's a constant battle.
There is a feeling among hard-core robotics folks that this level of simulation is either impossible or not worth the trouble. I tend to disagree. I think we got pretty far with the Anybots simulator; we did manage to evolve a neural network that balances on the simulator, and also balances the real robot. It's definitely a 'hard' problem to get a simulator good enough to be usefully predictive.
Depending on exactly what you're trying to do, of course...
Thank you. Cannot stress this enough. (Making said libraries portable helps, too!)
What made them popular was the design of the core languages. I started using Ruby because it was faster to type and easier to remember how to do things than Perl, not because it had more libraries, which it didn't.
The problem with Scheme is that the core language isn't terse enough, and so it gives the impression that it will be hard to do things. And that's correct. Scheme requires much more typing and is harder to remember than Ruby.
Consider:
Ruby:
h = {}
h[:foo] = "hi"
h[:foo] #=> "hi"
h[:bar] #=> nil
Scheme (Chicken): (define h (make-hash-table))
(hash-table-set! h 'foo "hi")
(hash-table-ref h 'foo) ;; "hi"
(hash-table-ref/default h 'bar #f) ;; #f
That, in a nutshell, is why people don't use Scheme. The people who made Perl etc. popular hate typing, and the core language of Scheme forces you to type a ton. There are other problems like really slow string functions, things that should be core being in SRFIs, libraries being called "SRFI 18" rather than normal things like "threads" so that it's extra hard to tell where a function is coming from, where its documentation is, or what you have to import to get it. Lack of libraries (if indeed that's a problem for you) is downstream of the core problem, which is that Scheme has a lot of clumsy design features that discourage would-be library writers from using the language a lot.This isn't a Lisp problem, it's a Scheme one. A Lisp with a better core and enough users would get lots of libraries eventually, just like any language.
I think Scheme is good for teaching though, and would rather learn it in a course than Python.
You say libraries aren't the issue, but the discussion is about a blog pst that said: "And why Python, then? Well, said Sussman, it probably just had a library already implemented for the robotics interface, that was all."
I'm sure your experience is grounded in a general reality. But the post you disagreed with was about a specific case: i.e. the one described in the blog post.
The problem, at MIT and elsewhere, is that hackers don't like hacking Scheme enough. Python has more libraries than Scheme now, but that's not the main thing that made more people use it. People use it because they prefer the language. This is something that Sussman and others at MIT should be trying to understand, but it doesn't strike me that they are trying to understand it. They're just saying "Python has a better robotics library -- oh well!" as if this were something completely random that they have no control over. That doesn't seem like the sort of attitude that produced Scheme in the first place.
My point of contention with the comment I replied to is the idea that fixing the problem is a question of writing more libraries for Scheme. Writing or interfacing to libraries for numerics, 3D graphics, etc. is a trivial task compared to making a language hackers love.
Now, maybe hackers' distaste for Scheme is Scheme's fault, or maybe it's hackers'; but in any case, the issue is with the core language, not the libraries. And based on my personal experience with Scheme I would say that enough of the fault lies on Scheme's side that it's worth fixing.
It is no accident that it survived almost exclusively in non-saltmine sanctuaries like MIT, where industry herdthink held less sway. In the linked article, Sussman directly admits that he is unable or unwilling to fight back against the intellectual decay that has consumed non-academic programming.
He has decided to "go with the flow" - namely, the flow of industrial sewage into students' heads.
user> (def h {:foo "hi"})
#'user/h
user> (h :foo)
"hi"
user> (h :bar)
nil
The main difference with the Ruby is the immutable by default data structure, which is why I replaced the assignment with a literal definition of the map. In any case, I think this demonstrates how Clojure has stolen some of the good ideas from Ruby and Python in addition to stealing many of the best ideas from other Lisps.Scheme (PLT)
(require scheme/foreign)
(unsafe!)
(define my-c-lib (ffi-lib "libmylib")) ;; loads libmylib.so
(define my-c-func (get-ffi-obj 'my_c_func my-c-lib (_fun _long -> _long)))
;; The C code does not need to take Scheme into account--
;; Existing C libraries can be interfaced with Scheme
;; with a trivial amount of effort.
C (to be linked against Python code-- Python can load the resulting shared library as if it was written in Python). Notice that all this code does is interface Linux's htonl function to Python: #include <Python.h>
#include <netinet/in.h>
static PyObject *
py_htonl(PyObject *self, PyObject *args) {
long my_arg;
if(!PyArgParseTuple(args, "l", &my_arg))
return NULL;
return PyBuildValue("l", htonl(my_arg));
}
static PyMethodDef methods[] = {
{"htonl", py_htonl, METH_VARARGS,
"Demonstrate Python's C interface\n"}
};
static char module_doc[] = "Demonstration";
PyMODINIT_FUNC
initfunc(void) {
PyInitModule3("mylib", methods, module_doc);
}People defending what's right can say one should do it because it's right. But people defending something they know is basically wrong can't say one should do it because it's wrong. So they look around for another word, and "practical" is usually the first they find.
I think "practical" often means choosing your battles. Sussman's choosing to fight the battle of explaining some syntax to his students rather than the battle of implementing a real-time robot control library from scratch in a language where no implementation supports real-time very well. Sun-Tzu would approve.
It's not evident from Andy Wingo's blog post, but just to clarify, Gerry didn't choose Python over Scheme: a committee did. Gerry said that when they had their revelation about the state of computer programming in 1997, he and Hal Abelson decided to stop teaching 6.001, and they eventually stepped away from the course altogether. (I believe Gerry returned to teach the class for the final term it was offered, but he didn't get into that last night; I could be wrong.)
Gerry went on to say that 6.001 essentially languished until sometime around 2007, when a committee got together and redesigned the introductory EECS curriculum to be what is now 6.0[012]. He didn't say whether he was on that committee, but I got the impression he was not. He appeared to be speculating when he offered the reason why Python was chosen. It was an offhand remark, something to the effect of (and I'm paraphrasing here), "And why Python? I suppose there were already good libraries for controlling these robots."
It sounded like Gerry explicitly chose not to fight any battles at all on this issue, and simply walked away resigned to the fact that computer programming, and engineering in general, are much different now than they were when he, Hal and Julie wrote SICP.
Two more things:
* I don't recall Gerry using the word "practical" even once while reciting his short anecdote.
* Gerry continues to teach with Scheme, not Python, in 6.945, his advanced topics course.
He wanted to do a course about robots, and according to him, the interface to the robots was Python, which was otherwise an adequate language.
If you want to make a case to the contrary, it should be rooted in the specifics of the situation.
(define (deriv f)
(define (f-prime x)
(/ (- (f (+ x dx)) (f x))
dx))
f-prime)
jeez, I wish it was easy to do that in Python. Python's main limitation, IMSHO, is lack of homoiconicity. Yes, I said it! dx = 0.00001
def deriv(f):
return lambda x: \
(f(x + dx) - f(x))/dx
In [11]: def cube(x):
....: return x*x*x
....:
In [12]: deriv(cube)(5)
Out[12]: 75.000149996640175
I'd also so that most (high school) educated people find infix easier to read than prefix, so isn't the homoiconicity a detriment to readability in this example (and any involving mid sized arithmetic expressions).I love scheme (alot more than I do python), but the only example that seems "impossible" to do is to implement a large subset of <language> in <language>.
You could obviously implement, a scheme-ish lisp in python, but there are alot of advantages to the host and guest languages being similar (or so that berkley professor would have me believe) that you would miss out on.
(You would also need a scheme expression reader in python... which I'm just itching to write now ... )
the example is from sicp: http://tinyurl.com/cubk49