Case Study #1: Robert the Luggage Bot
Let's start with something simple.
Here's version 1 of Robert.
This bot is designed to hover at a constant altitude from the ground beneath, remain fairly stable, and generally hold whatever you need it to hold gently and carefully.
So, in order to function he needs the following things:- Altitude control - He needs to know how far away the ground beneath him is, and then rise or lower as needed.
- Angular control - He needs to stay stable, with at least one section that is flat for you to place your objects on.
So first, let's take a look at his chassis.


Here we see that he is chiefly composed of two props: A circular base to rest your objects on, with a nice border around it to keep them from falling out which is no collided with the base only.

On the underside we see that he has a simple entity marker to link to the border prop, a control expression chip, and a ranger to determine how far away from the ground he is.
On to the coding now. E2 Code:
@name Robert the Luggage Bot
@inputs Alt Border:entity
@persist Plate:entity
@persist Ang1:angle Ang2:angle Vec:vector
if(first()){
Plate = entity():isWeldedTo()
}
runOnTick(1)
#Angular control
Ang1 = -Border:angles()*1000
Ang2 = -Plate:angles()*1000
Border:applyAngForce(Ang1 + $Ang1*5)
Plate:applyAngForce(Ang2 + $Ang2*5)
#Altitude control
Inc = 50 - Alt
Cur = Plate:massCenter():z()
Cen = Plate:massCenter():setZ(Cur + Inc)
#Motion control
Vec = (Cen - Plate:massCenter())*1000
Plate:applyForce(Vec + $Vec*5)
Remember: Adding # allows you to add comments to your code that will not interfere with it, which is useful for helping you and others understand what different parts do and what they are for.
Now let's look at what we already have for Robert on startup. E2 Code:
@name Robert the Luggage Bot
@inputs Alt Border:entity
@persist Plate:entity
@persist Ang1:angle Ang2:angle Vec:vector
if(first()){
Plate = entity():isWeldedTo()
}
runOnTick(1)
The E2 is welded on spawning to the circular base, so we can easily find that as it uploads. Therefore, we need to persist Plate as an entity variable to ensure that the code remembers it. We're using an timer (runOnTick(1)) to have the chip execute whether it's inputs change or not (Important if the ranger distance exceeds it's max, otherwise it would realistically change constantly).
Moving on to the angular controls, we're just going to use a very simple applyAngForce code. E2 Code:
#Angular control
Ang1 = -Border:angles()*1000
Ang2 = -Plate:angles()*1000
Border:applyAngForce(Ang1 + $Ang1*5)
Plate:applyAngForce(Ang2 + $Ang2*5)
We simply take the E:angles() of the Plate and Border entities and negate them each with a fairly decent multiplier. This will keep the bot fairly stable in the air.
Next, the altitude control. E2 Code:
#Altitude control
Inc = 50 - Alt #Change of altitude needed
Cur = Plate:massCenter():z() #Current altitude
Cen = Plate:massCenter():setZ(Cur + Inc)
This code alters Cen, the vector variable that the bot uses for it's motion control, to meet a Z value that will theoretically be the correct 50 units from the ground that it wants. We don't need to persist Cen because it's worked out each time the chip runs and is used in Vec for the motion control (Which is persisted).
Lastly, the motion controls. E2 Code:
#Motion control
Vec = (Cen - Plate:massCenter())*1000
Plate:applyForce(Vec + $Vec*5)
Simple enough, applyForce (Using the traditional formula of Vector = (Destination - Location)*Multiplier) keeps the Plate entity in the air according to the Z value set by altitude control earlier, and similarly leaves it floating rather freely in place according to whatever way you whack it.
Bookmarks