Notifications
Clear all

Building a Neural Network From the Ground Up

22 Posts
4 Users
13 Reactions
1,040 Views
Inq
 Inq
(@inq)
Rocket Scientist or Space Cadet
Joined: 5 years ago
Posts: 2071
Topic starter  

Posted by: @robotbuilder
↑

@inq 

Could be built out of light weight foam. It just seems a good idea so you can leave it alone while it uses the guards as feedback to the neural network when it tips too far. Maybe with sonar obstacle avoidance so it learns to balance while changing direction all by itself.

-- attachment is not available --

You definitely have the best solution, but what I'm getting at... is it's a somewhat bigger scale!  🙄  

image

This is going to be the Test Mule! (I'll have to come up with a good name) 700mm tall, 200mm wheels, total weight around 2.5 kg.  

The one it will hopefully morph into will be about 1800mm and probably around 4 kg.  But it is merely a figment of my imagination still.  

Inq

P.S.  What a hoot!!! - https://creatures.com/tools/animal/mule-name-generator

 



   
ReplyQuote
Inq
 Inq
(@inq)
Rocket Scientist or Space Cadet
Joined: 5 years ago
Posts: 2071
Topic starter  

Posted by: @robotbuilder
↑

Can't wait to see your progress on your ANN controlled balancing robot.

No pressure there!  😆 



   
ReplyQuote
Inq
 Inq
(@inq)
Rocket Scientist or Space Cadet
Joined: 5 years ago
Posts: 2071
Topic starter  

Posted by: @robotbuilder
↑

@inq 

Could be built out of light weight foam. It just seems a good idea so you can leave it alone while it uses the guards as feedback to the neural network when it tips too far. Maybe with sonar obstacle avoidance so it learns to balance while changing direction all by itself.

-- attachment is not available --

This has been bouncing around in my head for a few days.  With a little add-on, it'll solve a problem I've been struggling with:

  • I'll be discussing these issues in detail soon, but once I get a genome out of the virtual model and put it on the physical bot, I don't really trust it.  Did I model the Physics simulation accurate enough?  Did I measure the properties of the physical bot accurately enough?  Did I simulate the gyro/accel noise enough that I found in this topic?
  • But even if it nails it the first time.  Ha! 🤣 I want it to learn on the bot and improve.
  • But improving entails throwing another genome at it.  There's just as much chance that'll make it do a face plant. 
  • I was trying to strategize how to gauge "going bad" but still savable and switching back to the "pretty good" genome quick enough to let it recover. 

But as you mentioned, I should find an angle that the motors have enough torque and the tires enough traction to re-stand once falling on a kick-stands.  Then I went one step further (in my mind) to put wheels on them... aka training wheels.  



   
ReplyQuote
robotBuilder
(@robotbuilder)
Member
Joined: 7 years ago
Posts: 2581
 

@inq 

So you are wanting to evolve a neural network on a virtual robot rather then use a neural network to allow a physical robot to learn stand up with reinforcement learning?

 



   
ReplyQuote
Inq
 Inq
(@inq)
Rocket Scientist or Space Cadet
Joined: 5 years ago
Posts: 2071
Topic starter  

Using the ANN technique described above, the sketch ends up being pretty tiny.  It uses three libraries which ought to be no surprise.  It uses a library to access the LSM6DSV 6DoF sensor as input, a library to perform the ANN Inference and two instances of a Stepper driver for output. 

If you were interested, the 6DoF and Stepper driver could probably be replaced with your preferred ones.  These are no-frills versions.  For instance:

  • The 6DoF returns only raw data and doesn't filter, smooth, or convert to metric units, but it is blazing fast.
  • The stepper driver is like-wise bare bones and only has the ability to instantly switch to a new speed.  It does not do any acceleration smoothing.  But as you'll soon see, the Genome is responsible for acceleration!

The Inference library handles all aspects of the previous tutorial posts.  You update the input with data from the 6DoF sensor, call Inference() to get the output and pass on to stepper motors.  This runs at 7.5kHz!  I plan on publishing all three libraries, but I think @bryon suggested I put them up on GitHub.  I need to figure that out.

If there aren't any questions at this point, I'll start doing posts on the theory and coding of the Genetic Evolution.  They may be a little slow coming, I do have house projects as well as having started back to school three days a week.  Ugh! Homework!

I want to point out that the libraries including the Inference one don't need to change based on enhancements to the robot.  Going from the current 2D motion to a full 3D moving, turning, stopping, getting shoved (reasonably 😉) will not require any changes to the libraries.  In fact the only changes to this sketch will be to upgrade the Genome, likely getting significantly larger and having two outputs, thus giving commands to the separate stepper motors.  

One of the first upgrades once working with the real robot will be to turn on WiFi communications and simply update the Genome OTA.  Currently, if you take out the timing code and ignore the spacing and comments, the actual coding is less than 60 lines!

Here is the output, showing the initialization of sensors and the converted Genome into the arrays of the ANN.  At the bottom, some timing results showing it is running at 7.5kHz.

Serial Output

Inqster 1.0
LSM6DSV running at 7.5kHz
Brain
  GENOME: -1772379524
  Input array has 3 floats!
  Returned array has 1 floats!
  Input[0](3, 1) @ 0x3fcec4c0
           0
           0
           0
  Weights[0](12, 3) @ 0x3fcec380
  -0.0501952   -0.014164    0.155816
  -0.0353582   -0.156778   0.0395821
    0.474306   -0.185643  -0.0354818
  -0.0371802   -0.538911   -0.218068
         ...         ...
   0.0447599   0.0163717    0.113991
 -0.00387969    0.145845  -0.0256889
  -0.0166419    0.252368    0.205424
   -0.151702   -0.111295   0.0126698
  Biases[0](12, 1) @ 0x3fcec410
   0.0498158
    0.643197
   0.0625386
    0.123186
         ...         ...
  0.00932545
   0.0832527
    0.116721
   -0.131441
  Hidden[0](12, 1) @ 0x3fcec4f8
           0
           0
           0
           0
         ...         ...
           0
           0
           0
           0
  Weights[1](1, 12) @ 0x3fcec440
    0.191943   -0.304522    0.122252   -0.255301  ...          0.33    0.127799    0.358677   -0.175165
  Biases[1](1, 1) @ 0x3fcec470
   -0.646022
  Output[1](1, 1) @ 0x3fcec554
           0
(2) DRV8825 Steppers are ready.
7.5 kHz
7.5 kHz
7.5 kHz
7.5 kHz
7.5 kHz
7.5 kHz
7.5 kHz
7.5 kHz
7.5 kHz
7.5 kHz
7.5 kHz
7.5 kHz
7.5 kHz
7.5 kHz

 

Sketch

#include <InqLSM6DSV.h>
#include <InqInference.h>
#include <Inq8825.h>

#define VERSION "1.0"	// Last updated 2026/08/25

#define TIMING true		// set to false to remove timing code.

// Pins for SPI
#define PIN_MISO 15
#define PIN_CS   16
#define PIN_MOSI 17
#define PIN_SCLK 18
#define PIN_INTR  3
// Steppers
#define PIN_STEP_L       4 
#define PIN_DIR_L     	 5
#define PIN_STEP_R       6 
#define PIN_DIR_R     	 7
#define MICRO_STEPS     16

#define MAX_RPM		500.0f

// Base64 Genome created by Genetic Evolution Model
const char genome[] PROGMEM = 
    "AwADAAwAAQB8oluWfJlNvQIQaLwkjh8+y9MQvXaKIL7iICI9NdjyPkcZPr5qVRG9"
    "OUoYvRD2Cb8+TV++ffkpPdmJX7rdRSq9gSAePtPh1r0qoyg8oB9BvZ+3cTyyKZc+"
    "ByEDvXTU8j6WA2w+M1Y3Pf4dhjw3dOk9W0J+u15YFT5xcdK8hFSIvFE2gT7HWlI+"
    "4VcbvsPu473blE88owtMPZeoJD86FIA9uUj8PQFXUz7yngs+8MKevqyfJb3ByRg8"
    "YYCqPTgL7z16mAa+x4xEPlnqm76AX/o9y7aCvjRq4D3p2r++EIvSviV7LT+/9ag+"
    "pd0CPnOktz5vXjO+sWElv1";	
	
InqLSM6DSV imu(PIN_MISO, PIN_CS, PIN_MOSI, PIN_SCLK, PIN_INTR);
InqInference brain(Activations::Sigmoid);
Inq8825 left(PIN_STEP_L, PIN_DIR_L);
Inq8825 right(PIN_STEP_R, PIN_DIR_R);

float* input;
float* output;

void setup() 
{
    Serial.begin(115200);
    delay(1000);
    Serial.printf("\nInqster %s\n", VERSION);

	if (!imu.begin())
		halt("Sensor Failure");
	Serial.printf("LSM6DSV running at 7.5kHz\n");

	Serial.println("Brain");
	input = brain.begin(genome);
	if (!input)
		halt("Brain damage");
	brain.print(true, true);
	
	Serial.println("(2) DRV8825 Steppers are ready.");
}

void halt(const char* msg)
{
	#define LED_PIN 48
	Serial.println(msg);
	bool on = false;
	while(true) 
	{
		neopixelWrite(LED_PIN, (on = !on) ? 16 : 0, 0, 0);
		delay(1000);
	}
}

void loop() 
{
	// Get data from 6DoF sensor
	RawLSM6DSV rawData = imu.readThrottled();
	
	// Populate input data array and call Brain inference.
	input[0] = rawData.gY;
	input[1] = rawData.aX;
	input[2] = rawData.aZ;
	output = brain.inference();
	
	// Pass it on to steppers.
	left.setRPM(output[0] * MAX_RPM);
	right.setRPM(output[0] * MAX_RPM);	
	
	#if TIMING		// Timing data for our Inquisitiveness!
	static uint32_t t0 = micros();
	static uint32_t cnt = 0;
	uint32_t t = micros() - t0;
	cnt++;
	if (t > 1000000)
	{
		Serial.printf("%.1f kHz\n", cnt * 1000.0f / t);
		t0 = micros();
		cnt = 0;
	}
	#endif	// TIMING
}



   
Lee G and robotBuilder reacted
ReplyQuote
Inq
 Inq
(@inq)
Rocket Scientist or Space Cadet
Joined: 5 years ago
Posts: 2071
Topic starter  
Genetic Evolution Demo Teaching a Neural Network
Above, we discussed the use of an already solved Neural Network.  This topic is merely about the demystification of the Computer Science technology behind Neural Networks, and by extension all AI including chat boxes, ChatGPT, and all the other AI offerings.  In this chosen example of a self-balancing robot, the reality is simply a couple of matrices doing a few multiplications and additions with a few adjustments to add a bit of non-linear capability to the final answers.  The entire program (Arduino Sketch) that is unique to balancing a 2-wheel robot is about 60 lines of code.  If you strip away all the sensor input side and all the motor output side, it waters down to 1 line of code and a blob of data.
 
If you have or are 😉 building a self-balancing robot, you might compare this to all the code to massage the sensor data into something physically associated with balancing.  You would then need to consider the PID tuning portion.  And then factor in the time required to teach (tuning the PID).  And then consider that if you change any one thing on the physical robot, you have to re-tune it again.
 
The discussion in this topic will continue now with one technique of letting a Neural Network train itself.  We'll be working with Genetic Evolution.  Another inflated obfuscation of the Computer Science world to describe something closer in complexity to throwing darts at a dart board.
 
The following YT shows a program being written to use Genetic Evolution to solve problems.  All attempts will be made to make it generalized so that it can be used on any Neural Network for any use case.  Of course, this will be constrained by the limitations of the computer or micro controller it may run.  The eventual physical, 2-wheel, self-balancing robot is just a concrete example that is both fun to build and extremely graphic of what is accomplishing that seems non-trivial.  The point being, as you'll see... it is a trivial example of AI.
 
Posted by: @robotbuilder
↑

@inq 

So you are wanting to evolve a neural network on a virtual robot rather then use a neural network to allow a physical robot to learn stand up with reinforcement learning?

Now, to address your question... The short answer, Yes!  The long answer:

The Genetic Algorithm size and complexity should easily fit and run respectably on say an ESP32, ESP8266, RasPico, or other fairly powerful Micro Controller.  I will be writing that code here.  It would allow an MPU powered robot to learn, on its own in the physical world.  Several reasons cross my mind to do it virtually before doing it on a physical robot.  From least important (1) I can.  (2) I enjoy writing code when the results are rewarding.  (3) A self-balancing robot doing face-plants or running into walls (even with training wheels) for thousands of attempts doesn't bode well for my robot's longevity.  (4) But foremost, patience is not one of my virtues.
A few things to note as this runs: 
 
As there are tens of thousands of recordings, and I've looked at a few as it progresses through the evolution, you'd see many that face-plant, and then ones that try to catch itself, but fail and then ones that start to wobble around, drifting toward the limits defined.  Those are all between the ones shown that incrementally improve.  The primary portion of the score (we'll be discussing) is the amount of time before reaching a limit criteria.  Early on, it is falling over pass 80°.  Later ones, the limit is moving more than 0.5 meters away from the start position.  As can be seen, it is able to stay within those limits and toward the end, it successfully stayed over 5 hours.
 
Next up, the nuts and bolts of Genetic Evolution.
 
Inq


   
robotBuilder and Lee G reacted
ReplyQuote
Inq
 Inq
(@inq)
Rocket Scientist or Space Cadet
Joined: 5 years ago
Posts: 2071
Topic starter  
Aside / Excuse:  It's been a bit since my last installment.  I must say that returning to University after over 30 years has eaten far more time than I initially expected.  I had two goals:  take some courses just for fun that I didn't have time for my first go-around and to learn more about what makes AI work.  During my attempts at finding classes of the latter, I grilled professors, department heads and deans in Mathematics, Physics, Computer Science and Engineering.  I've drawn a complete goose-egg in the hard-core pure theory department.  I've found two in engineering, but because they are new programs and no students have the prerequisites yet to offer the classes.  They're slated for Spring of 2028.  During one of my meetings with a department head, we talked at length about my goals. Then abruptly, he asked if I wanted to teach.  I really didn't think he was serious and took it as a kind complement until a couple of days later, he CC'd me on an email to the engineering dean.  As I don't have a PhD, I can only teach as an "Adjunct" professor.  Basically, the salary amounts to the minimum wage here in the US.  It would barely pay for the gas and parking fees.  It would certainly not pay for the wear and tear on the car.  Anyway, I've been considering it for a few classes that I'd enjoy teaching.
 
Genetic Evolution
 
Reference:  https://www.abebooks.com/Genetic-Algorithms-Search-Optimization-Machine-Learning/32377554778/bd .  It even supplies code; it you can read Pascal, but these days, you can use libraries in your chosen language or just ask AI to write it for you.  
 
I gather that in the early days (this being 1950's and 60') AI was attempting to draw more conclusions from the way humans learned from childhood in the micro scale and human evolution in the macro scale.  Genetic Evolution Algorithms came from this latter approach.  As an overview, here is the briefest of summary of what goes on:
  1. From the primordial goo, an organism is created.  We're to ignore the Chicken and the Egg quandary.  It has a certain Genetic structure often called a Genome.
  2. Then, a whole bunch of them are created with the same basic Genetic structure.  This Population represents the birth of the species.
  3. Each Genome (the individual) is tested in an environment for the traits we want.  This often involves seeing what it does as a function of time... what it does when time starts, then 1 microsecond, 1 second, 1 year... later where it is and what it is doing is monitored.  This test is run until the individual does something terrible and "dies" or until a set amount of time.  In either case, it is given a Fitness value.  Think of it as a score card.
  4. The individual now mate.  The ones that die aren't in the gene pool anymore, so they cease to exist.  The next generation is then created by taking the best scoring ones and combining their Genomes to create the child of the next generation.
  5. A new Population is created of these children and is often the same size of the preceding generation.  
  6. We return to step 3 and re-test the new individuals.
  7. This is done until we "see" the traits we're happy with.  We get it to converge on the answer.  Otherwise, we see it giving us nothing approaching a solution, or we simply stop at some defined number of generations.
That's it, in a nutshell.  In the next installments, I'll go over each of these steps in detail but know there are no hard and fast rules.  There are plenty of opinions and each has its benefactors.  Feel free to ask questions, and I'll give you mine. 😉  Generally, the options work in certain cases, but not necessarily all.
 
Inq
 


   
ReplyQuote
Page 2 / 2