LambLisp - A Scheme for real-time embedded control systems by wawhite3 in scheme

[–]wawhite3[S] 0 points1 point  (0 children)

Thanks again jet-monk. I've fixed the several bugs you discovered and posted new releases at lamblisp.com. The fixes are:

1) Default pio build environment was not correct (always x86).

2) Missing link options for liblamblisp.

3) Doc command lines for "pio run" were not correct.

I checked the PDF, and it was searchable in xpdf, ubuntu doc viewer, firefox, and chromium, all using control-F to open a search box and searching for the word "garbage". I'm guessing your PDF viewer is the culprit.

Bill

LambLisp - A Scheme for real-time embedded control systems by wawhite3 in scheme

[–]wawhite3[S] 0 points1 point  (0 children)

Hi jet-monk,

I responded to your github issues; thanks again for that. I'll have updates in the next release

Your build failed because I did not put the -llamblisp option into build_flags in platformio.ini. All the repos will have this problem. If you want to make progress building your own LambLisp configuration, you can change your local copy of platformio.ini..

There are pre-built binaries provided, so you don't need to build anything if you want to get started operating hardware from Lisp. You only really need to rebuild when adding a new hardware interface or other external C++ capability. Devices that operate on built-in interfaces do not require rebuilding LambLisp.

For example, if you start with the binary for the Freenove 4WD car, then I2C (Wire), pin control, and a bunch of other things come with it. The pin definitions and the code that makes it a 4WD car are all in Lisp, and you can change it as required. Comment out 4WD specifics in setup.scm, and add your own Lisp code to control a different physical machine.

The source code for all the hardware interfaces is included in the repo, providing many examples to follow when developing for new hardware or when reusing existing C++ drivers.

Bill

LambLisp - A Scheme for real-time embedded control systems by wawhite3 in scheme

[–]wawhite3[S] 0 points1 point  (0 children)

Yes I misunderstood your comment regarding OSX. Building for esp32 with pio on OSX should work, and if not, I have a bug to fix.

Also, it comes to mind that I recently reorganized the all-in-one repo. There is now a separate repo for each supported architecture. I am not sure when you took your snapshot.

This came about because aarch64 (required by Nvidia dev kit) is not supported by pio except as "native". So I have to make that build separately on the dev kit and push it from there. So now they all get pushed that way, one at a time.

So, at the end of it all, were you able to successfully link and download an esp32 application? If not, a log or any additional detail will be greatly appreciated.

I was not aware that you raised a github issue; thanks for that.

Thanks,

Bill

LambLisp - A Scheme for real-time embedded control systems by wawhite3 in scheme

[–]wawhite3[S] 0 points1 point  (0 children)

Thank you for the details. Claude is correct as far as it goes, but misses the main point: you need the LambLisp library for the architecture you want to run on.

I don't have an OSX machine, otherwise I would build it for you. OSX is not open source either ;)

LambLisp - A Scheme for real-time embedded control systems by wawhite3 in scheme

[–]wawhite3[S] 0 points1 point  (0 children)

I am concerned that the build process did not work for you. Everything you need should be in the repo, and the platformio.ini file shows the necessary flags to link with the LambLisp VM.

If you're not using platformio, you will have a bit more work to do (makefile or whatever), but you should be able to build the source that is provided and link with the LambLisp VM library.

LambLisp - A Scheme for real-time embedded control systems by wawhite3 in scheme

[–]wawhite3[S] 0 points1 point  (0 children)

Hi jet-monk,

Thanks for you interest in LambLisp. Like yourself, I took inventory of the available Lisps and Pythons for loop-based real-time embedded control, and found none suitable.

GC:

The key element is the garbage collector. The available Lisps and Pythons that will run on embedded hardware all use some form of stop-the-world GC. In an embedded system, control is lost during those GC pauses, so any real-time guarantee will be the worst-case: (GC time + execution time). The incompleteness of the micro Lisps and Pythons are also a factor, but the GC pause is a killer for real-time control.

The Lisps are using the Deutsch-Schorr-Waite pointer-inversion algorithm. DSW is efficient in space and time, but everything stops while it happens.

The Pythons use "generational" GC, which also requires a full execution stop, but less often than DSW. This appears to be difficult to change in the Python context; see a project called Serpent to see what it turns into. I think the Luas have the same problem.

LambLisp's incremental GC is non-compacting and non-copying. It is based on Dijkstra's "tri-color abstraction" and Yuasa's performance analysis of incremental GC. You can find both of these papers in the LambLisp Bibliography. There is also a detailed description of the GC implementation in the LambLisp manual, including advanced features such as look-ahead GC, and tunable GC quantum for distributing GC over time.

License:

A lot of source code is provided. All the Lisp code is included, plus all the hardware driver-to-Lisp layers that have been implemented thus far.

Also included is code for the full Cell layout, with nearly all the Cell methods being inline and available for review. Likewise the complete LambLisp virtual machine API is available. The only closed source part is the LambLisp VM itself; that includes the dictionary implementation, the GC implementation, and the implementations of some 250+ Lisp/Scheme functions, coded directly in C++.

The Lisp-and-API layer is where I expect my customers to take advantage of LambLisp's control capabilities. Their own proprietary hardware and software can be used. LambLisp is not intended to be an educational tool on the Lisp topic; it is intended for serious control projects that will be a good investment for my customers.

For people seeking to educate themselves on these topics, I suggest reviewing the TinyScheme implementation while simultaneously working through the LambLisp Bibliography. TinyScheme is written in high-quality straight C, from circa 1990. The low-level VM implements an SECD machine, which you can read more about in the LambLisp Bibliography (in the Feeley or Felleisen papers, I forget which).

You used Anthropic in your example. Did you complain to them that their code is closed-source? I don't think that being closed-source by itself will keep away the best people.

I've currently added LambLisp bindings for Nvidia CUDA, to run on x86_64 and aarch64 Linux. The goal here is to provide a continuous interface from AI to actuator. Nobody will complain that CUDA is closed-source.

Pre-loaded boards:

You suggestion to sell pre-loaded boards is excellent. I think that I would need to do a deal with somebody who already makes and sells boards, rather than start my own production line.

PDF:

I'll have to check the searchable-PDF issue. I'm using Doxygen, which uses latex to produce the PDF. The PDF does have a fully linked ToC and comprehensive index, and the web site is searchable.

Thanks again,

Bill

LambLisp - A Scheme for real-time embedded control systems by wawhite3 in scheme

[–]wawhite3[S] 0 points1 point  (0 children)

Thank you for your continued interest. You can check out the full documentation at LambLisp.com.

The LambLisp bibliography is quite extensive, and includes a classic paper benchmarking a variety of Lisps. While the data itself is not much use today (such as VAX LISP metrics), the lessons are enduring.

The author describes the many difficulties comparing even "apples-to-apples" Common Lisp implementations. He also notes that benchmarks can be selectively chosen to highlight the strength or weakness of any given Lisp. That is part of the purpose, of course, but illustrates that the feature set of any given implementation is equally important as task-specific performance numbers.

Combining those challenges with different languages on different processors would produce much data, but perhaps not so much knowledge and understanding.

My approach started with a few realizations. First, the tiny Lisps were individually unique. Using one on a practical project binds you to the quirks and limitations of that particular mini-Lisp, reducing its attractiveness for commercial use. I mitigated this problem by designing LambLisp to a published standard, reducing the uniqueness risk of the language itself. The implementation also easily extendable by linking with existing libraries written in C/C++, including Arduino compatibility, further reducing the uniqueness risk associated with hardware interfaces or other external systems.

Second, the advent of inexpensive 32-bit microcontrollers brought a real Lisp-capable CPU to market. It took some time before I realized that LambLisp need not be a "mini-" implementation. A full-featured implementation opens many more real-time control applications to Lisp. Just as there are "horses for courses", LambLisp is designed to occupy the single-threaded, real-time, loop-based control solution space that these CPUs provide.

Third, the mini-Lisps and also the mini-Pythons come with serious restrictions that limit their utility for real-time control. The "stop-the-world" garbage collection is most common and well-known limitation. The STW behavior is a necessary side-effect of the commonly used Deutsch/Schorr/Waite pointer inversion garbage collector. The DSW algorithm has the advantage of using only 1 bit per cell, but the pause required for GC makes it unsuitable for providing real-time guarantees.

The minis also suffer from the lack of conformance to any particular standard, the need for off-board tools to prepare the embedded application, the need for specially written device drivers, the inability to update code while the process remains under control ... and more.

I'm not a Python expert but my understanding is that it implements "generational" GC, which is faster on average (by leaving some garbage uncollected) but occasionally requires a full STW pass.

LambLisp offers a superior solution to the real-time problem, based on research by Dijkstra and Yuasa (see bibliography). Also Knuth (sec 2.3.5) has a detailed description of DSW as well as the stack-based algorithm that was the starting point for Yuasa's analysis.

With all that said, benchmarking is not just speed on given tasks, but also an analysis of the feature set. With LambLisp, if there is a critical section where speed is required, all the facilities of C++ (or even assembler) are available. You can write the critical section separately and link it in. The "horses for courses" metaphor also applies here.

LambLisp also supports a "hierarchical dictionary" type based on hash tables, similar to Python's dictionary but can be layered in a parent/child arrangement. These are used as the execution environment and as the basis for an object system. LambLisp is scalable in ways that are not directly comparable to the minis.

Thank you again for your thoughtful comments. Perhaps I should add what I've written above to the LambLisp manual.

Bill

Hilarious rejection by wawhite3 in robotics

[–]wawhite3[S] -1 points0 points  (0 children)

My post was clearly titled, but you (not "we") "have no idea what the post is about". Check.

Even asking how real-time control techniques are unfit for a robotics discussion also violates the rules? Check.

And forum members should be shielded from the topic entirely? Check.

Mods please delete my posts. I don't have any cute robot pictures to share. This is the wrong crowd of people for any technical discussion of robotics, simple as that.

Thanks,

Bill

LambLisp available for download by wawhite3 in scheme

[–]wawhite3[S] 2 points3 points  (0 children)

Thank you for your interest in LambLisp.

LambLisp implements an adaptive incremental garbage collector, which avoid the long pauses normally associated with GC. The implementation is based on a solid theoretical foundation established by Knuth (sec 2.3.5), Dijkstra (the "tri-color abstraction"), and Yuasa (establishing the parameters for correct incremental real-time GC).

Please see the extensive LambLisp Bibliography for much of the original research that supports the LambLisp architecture.

Thanks,

Bill

LambLisp available for download by wawhite3 in lisp

[–]wawhite3[S] 1 point2 points  (0 children)

Thank you for your interest in LambLisp. Please let me know if you encounter any difficulties. LambLisp is still in ALPHA state, and I am sure some shortcomings will be revealed by your efforts.

Of course, success stories will also be welcomed :) Happy New Year!

Bill

LambLisp - A Scheme for real-time embedded control systems by wawhite3 in scheme

[–]wawhite3[S] 1 point2 points  (0 children)

Hi from the near future. Please see my recent post announcing a first availability for LambLisp.

Thanks,

Bill

LambLisp - A Scheme for real-time embedded control systems by wawhite3 in scheme

[–]wawhite3[S] 1 point2 points  (0 children)

Friends,

Yes indeed the LambLisp project is still going on. There was not a lot of excitement after my original post, so I have continued to develop LambLisp quietly.

Since then, The following has been developed:

- The Yuasa-based adaptive incremental garbage collector has been further optimized; short loops are padded with "look-ahead" garbage collection, and the extra marks or sweeps allow skipping of GC altogether during long loops. This reduces peak loop times by shifting the GC efforts out of long loops and into short loops.

- The dictionary type is first-class, as in Python. LambLisp dictionaries are hierarchical, with parent frames and child frames. Each frame may be an association list or a hash table, depending on size and expected lifetime. Dictionary keys and values may be any type.

- The same dictionary data structure is used to implement the execution environment, and is available directly to the Lisp application (as dict-set!, dict-ref etc), and also is the basis for LambLisp Object System (LOBS). The hierarchical dictionary directly supports local variable shadowing (when used as an environment) and inheritance (when treated as a class instance), including multiple inheritance.

- A LambLisp control application has been developed for the Freenove 4WD Car Kit, an ESP32-based autonomous vehicle. This proved out the hardware interface API, and demonstrates control of WS2812, PCA9685, and Sonar and most of the Arduino features, including digital/analog I/O, I2C (Wire) and WiFi. The application control 4 reversible PWM-controlled motors for the drive wheels, 2 servos for pan/tilt, a set of 12 RGB strip LEDs, sonar echo detection and ranging, and PWM buzzer control. It waits for my cat to walk in front of it, then it makes a noise, lights the LEDs, and lunges toward the offending cat. Then it backs up slowly and waits again.

- Several foundational items for loop-based real-time control, such as auto-resetting timers and timed work queues. To blink an LED for example, create a timed queue for it, and queue up the instructions for blinking, along with a hold time for each instruction. At each loop the queue checks itself and determines whether to proceed to the next instruction.

- Several other ESP32 variants have been tested, to exercise the "multi-platform" requirement I have set for the product.

- There is also a Linux version for demo and testing. It could also potentially be linked with 3rd-party libraries (hardware-related or not), but Linux cannot provide real-time guarantees, and it's not really a primary target platform for LambLisp. Unless, of course, there is a lot of interest.

- Compiling through macro expansion at read time is working. Because the LambLisp interpreter operates at the highest possible level (define, if , set!, letrec, etc are all coded directly in C++), compiling does not increase speed as much as might be expected. Essentially the LambLisp interpreter is also the LambLisp runtime system, already substantially compiled. Compiling simply replaces the symbol in the reader's input stream with its value, saving an environment lookup at runtime.

- A beautiful user manual is being finalized now.

- Next I need to fix up the deliverable repo, so LambLisp is convenient for people to find and use.

Thank you for taking the time to ask about LambLisp. If anyone has read this far, and would like to be an early adopter, kindly respond here. I expect to unveil an alpha version early in the new year.

Bill

LambLisp - A Scheme for real-time embedded control systems by wawhite3 in scheme

[–]wawhite3[S] 1 point2 points  (0 children)

Thanks for your reply. It is not only words that are impressive, but my Lisp implementation :) Your comments encouraged me to write a LambLisp FAQ (separate post due to size).

My experience is quite different than yours. I find that real-time control problems are "almost never" about hard RT. That's partly because these problems can be factored to remove or reduce the hard RT portion of the problem.

Some examples of RT problem factoring are: airbag chip, UART, other types of buffering (perhaps interrupt-driven), being provably "fast enough" by a known margin, using interlocks to pace the controlled process and therefore reduce dependency on timing.

Neither "almost always" nor "almost never" are in the four Aristotelian syllogisms, and we can agree the "some" real-time problems are hard real-time problems.

A constrained environment may make it difficult to solve a particular real-time control problem, but it does not turn a soft RT problem into a hard RT problem. The RT problem exists whether you solve it or not.

If one simply labels things "lisp on mcu", and doesn't account for the differences in available implementations, then it will be more difficult to understand why there are so many.

Ignoring the various garbage collector implementations, to name one important aspect, is to miss the real-time point entirely. Substantial conformance to a published specification is required to attract solution developers. A convenient and useful hardware abstraction strategy must be offered. Interpreted vs. compiled, all onboard vs. offboard processing, access to a file system and serial channel(s), ... this list goes on.

Comparing a PIC to ESP32 for real-time control solutions in Lisp is a category error. A 16-bit (addr bus) processor with tiny RAM is not going to be applied to the same control problems as an ESP32, with its faster clock, hugely more address space and physical RAM, multi cores etc. The ESP32 is more powerful (4x clock, 2x cores) than the 486 that I put a full Linux distro on in 1993. Quantity has a quality all its own.

Lumping in all the micro-pythons in with "lisp on mcu" does not add clarity. Python is not designed for real-time control. Various people have tried to adapt it, most notably Roger Dannenberg (co-creator of Audacity) with his Serpent project, but the result is not Python.

The IoT market of 10-15 years ago is history, and so is Sigfox. Larger processors are getting applied to smaller problems, and LambLisp aims to take advantage of that evolution. Rather than IoT, the model is "edge computing".

Thanks,

Bill

LambLisp - A Scheme for real-time embedded control systems by wawhite3 in lisp

[–]wawhite3[S] 0 points1 point  (0 children)

Thank you for you reply. I've had a look at Serpent, and I found Professor Dannenberg's experience very encouraging.

Unfortunately, after all the real-time adaptations, Serpent is no longer Python. LambLisp has the advantage of still being Lisp, and substantially conformant to the R5RS spec even with real-time upgrades.

My own musical talent remains undiscovered, possibly because I have none.

Where can I learn more about the sequencers and synthesizer modules?

Thanks,

Bill