Newer
Older
# Inverted Pendulum
To finish Neil's [maths class](http://fab.cba.mit.edu/classes/864.20/index.html) and to walk myself through some control basics, I'm going to try to control an inverted pendulum system.
## The Simulation
One first step is building an ODE simulation of a pendulum, and rendering that. I can do this pretty easily by pulling code from my earlier javascript pendulum, just moving the platform left/right instead of up/down. I should hope to build an understanding also for simulation time / weight / units relate to world units, so that I can match it against the world.
Where $`\theta`$ is the angle of the pendulum, $`g`$ is gravity, and $`l`$ is the length of the pendulum.
This makes sense: the angular acceleration is equal to the force on the pendulum, which is a function of gravity, the length of the stick, and its current angle. But what of the cart?
```math
l\ddot{{\theta}} - g\sin\theta = \ddot{x}\cos\theta
```
Where $`x`$ is the position of the cart. This also makes sense! The acceleration of the cart ($`\ddot{x}`$) is related to the horizontal component of the angular acceleration of the pendulum.
In my tiny simulation, I'm going to drive the cart acceleration: I'll do this in hardware as well, so I should be able to expect some $`\ddot{\theta}`$ given an $`\ddot{x}`$
```math
\ddot{{\theta}} = \frac{\ddot{x}\cos\theta + g\sin\theta}{l}
```
I'm pretty sure this is enough to let me write some javascript. Since time is cheap (i.e. computing) and this is simple, I can even default to ahn euler method.
Yeah, this is fine... here's the free swinging, obviously we are used to the real world being *damped*

I'll add keys... ok, just want to get a clip of nearly balancing this human-in-the-loop... it's tough, time is not real yet either:

OK, for time, I'll use JS timers... Got it, running in realtime now. OK.
cool, this works, and euler probably OK because we are already running in realtime. if anything, do better at JS handoffs, events, protocol, etc. control.
I've tooled around with PID now, so I can adjust these parameters by hand, next up is search for PID params.
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
## The Stepper Driver
I want to build a new stepper driver (code) for this. Currently, my driver & hardware pair has these settings, maxed:
| Setting | Units | Value | Alt Units | Value |
| --- | --- | --- | --- | --- |
| steps / mm | - | 231 |
| acceleration | mm/s^2 | 30 | m/s^2 | 0.03 |
| top speed | mm/s | 20 | m/s | 0.02 |
Although it would seem as though I've made some mistakes in implementation, because this seems pitifully small in terms of 'Gs' - but observed acceleration seems to be near or beyond 1G.
- first, cleanup existing code
- steps/unit as a float,
- underlying state / operation same as current, but understand and document limits
- stepper becomes responsible for acceleration, watch world units, timers
- stepper should become responsible for limits: I want to bake safety into hardware. as a result, it will also be master of its own absolute position.
- to start down the new path, I'll roll it up to accept acceleration commands, in world units `m/s^2`
- eventually I'll want to bundle data packets... RIP msegs
## The Pendulum Hardware
I'm planning on using [this axis type](https://gitlab.cba.mit.edu/jakeread/ratchet) as the 'cart' for the pendulum project. This is part of a larger machine project I am working on in the mean time.


This might prove to have some limits: these are designed to accelerate at a decent clip, but not hit huge top speeds. The 6.5:1 reduction there really kills and speed desires. I think I'll get through the simulation, get a sense of what kinds of accelerations and speeds are required, and revisit this if it's necessary.
There's some CAD and sensor reading here, as well - I'll need to make / print a pendulum bearing / encoder situation, write an encoder driver, and then very likely should filter that encoder data to build a state estimator for its current position.
## Software Architecture
One of the real puzzles here - and I hope this will unlock some secrets for future, more general purpose control of machines - is how to handle the relationship between realtime-worlds (embedded code and *genuine* physics) and asynchronous worlds - like the javascript / networked runtime and simulation.
My suspicion is that *sourcing* time from the lower levels is the move, i.e. track state / time advancements from the bottom, and somehow trickle those up.
## The Actual Control
Here's where I know the least... again, starting point is certainly the simulation, with keyboard inputs to play with. I hope to learn from the simulation:
- what accels, what speeds are necesssary for success (human controller)
- above, w/ relationships to pendulum weight / length,
From there, I'd also like to plot the phase space of the system. I have some idea that one control strategy would be to run a kind of 'path planning' inside of this space... if any point in the space represents a particular state, plot a course to the state we are interested in being at.
I should also do some lit review, that should start here.
[youtube pendulum 1](https://www.youtube.com/watch?v=XWhGjxdug0o)
### Swing Up and Balancing
I imagine I'll start with balancing, as swing up seems to require some next level magic. In [the first video above](https://www.youtube.com/watch?v=XWhGjxdug0o), these are two distinct controllers!
### Learning
The idea is to craft a best-practices-and-all-the-priors model and controller first, and *then* start cutting pieces out to replace them with learning / search.
# Log
## 2020 05 16
OK, here we go. PID is step one. Did that.
I'm trying to plot error, and error derivative. Trouble with flow control into the chart... strict flowcontrol is tricky, espcially when things are gated on one another. Might want to have a mechanism to clear previously-put tokens... hmmm
OK, sorted that but just temporarily. To close tonight, I should take a video of this (expanding this canvas or shrinking the charts) and then, to run simplex, I should:
- write an I term
- plot error, maybe not error derivative, plot control output (easier to visualize pinning at acceleration limit, then)
- have an error metric...
- adjust the simulation: make time-step size variable. might want to do 0.1ms, not 1ms...
- adjust the simulation: make state variables for # of iterations between draws, this is the 'timelessness' - draw updates will still happen at set-time intervals, yeah?
- each fn call will run for a set number of counts, now we can spawn two simulations, one that is constantly searched-over, the other inherits last-best-PID set from the other, and runs 'realtime' to demo progress -
I really expect / hope to show that this expands to hardware, I'd be more pleased by a hardware-in-the-loop system, where I use 'realtime' alignment to a known simulation, and a simultaneous simplex search for PID parameters, and in turn update those to the realtime thing... this is probably cool as well because simplex should adapt (?) to a changing evaluation function (i.e. it's searching the simulation: the simulation is being adapted to suit the real world)... could be neeeeat
## 2020 05 06
I expect the *result* of the control-with-search experiment will be that success does not look like replacing the control algorithm, but with searching for parameters in the simulation used to to prediction. At least - that aspect in realtime. Since time for simple systems becomes essentially free when we simulate them, we can use these simulations to search for controllers over thousands of 'epochs' - then we just have to plug them into our physical systems ... their 'digital twins' - so, the pain there is in aligning system parameters. However, prediction here works on a much faster time step: we have the last-state, and a prediction of the next state, given our simulation. We also have a physical equivalent of this. Say we just input control variables open-loop into the physical system, read its state, and (we are potentially doing this near or upwards of 1kHz), work to match *our* predicted next-ms-state to the system's real next-ms-state. So we can do fast simulation / physical alignment, and then lean on the free time in the simulation to learn higher order control. Perhaps, or likely, that a *good* implementation of these mixes both, so that it's always doing both - we can imagine the computer sort of every-so-often receiving 'real' data, using that to check / match its model against the world, and then (in the remaining cycles inside of the ms: 4 000 000 on a 4Ghz clock), continue to imagine possible futures / trajectories / control parameters. OK.
## 2020 04 05
I've turned all of my hardware and frameworks back on after ~ 1 mo away from code, so I'm just note taking on what my steps are for this thing, and some other observations.
I figure I should first build this virtually, in simulation, and then attach that to hardware. Since it's appropriate, I'll also try to take this opportunity to ~~break~~ explore some of the architecture decisions I made while I was building [squidworks](https://gitlab.cba.mit.edu/squidworks/squidworks), which I am ready and excited to revisit.
I should keep things simple and move fast, so as much as possible I'll retain most of squidworks' function. To start, this should just mean (1) writing ahn hunk that runs the simulation, and does control, and (2) writing a new stepper driver.
- current acceleration control is not cool enough for this project. also, limits for the same should be found downstream at the motors. motors have no guarantee that they have a faithful master, should protect themselves. how to find and auto config all of this?
- current stepping code is also sort of limited. I figure I should roll new, simple codes that begin with running accleration, and maybe even track position state at the endpoint as well - lets build from the bottom up here, since remote states are always a PITA. I like the thought that in the future, states are queried-only, so we can put heavy stuff like position in these areas
I am into this last point. I want a stepper driver that knows (1) where it is, (2) what its limits are, and then (3) can accept accelerations as inputs. It should be dampening; when there is no requested accel, or it's not near an edge (that it cannot deccel into), it deccelerates. This will put enough intelligence into the motor that I can build other APIs on top of it, which hopefully will end up looking like some kind of bussed - and - timestamped - moves to make... ?
I have some code cleanup to run first, I think. First would be rebasing scuttlefish into cuttlefish. Then, since I'm going to break the stepper otherwise, I should branch ponyo.
OK, done with that... and notes here... I suppose the simulation is my first order, as it's a javascript world for me for a few minutes, some chance that I might wrap on new protocol stuff before I get too far into this, it would be cool to use this to push all of that.