openroberta-lab
openroberta-lab copied to clipboard
Lego Boost Support
Is your feature request related to a problem? Please describe.
- Add support for Lego Boost robots so that newer developers could use Open Roberta to program their robots without being tied to the proprietary Lego Boost App. The Lego Boost App is only available on certain platforms and is only supported by specific devices making programming difficult. There exist open source python libraries as well as other closed source applications that provide interfaces to Lego Boost, but they require a higher level of programming skill and experience to use.
Describe the solution you'd like
- It would be great if OpenRoberta could be extended to support Lego Boost. Perhaps by utilizing the pylgbst library developed by Andrey Pokhilko (https://github.com/undera/pylgbst). This library could be wrapped in a server interface or some other glue layer to provide interaction between OpenRoberta and the pylgbst libraries. Alternatively, Picaxe provides an S2BApp that has an http interface that can be used to communicate with the robot, but this app is currently not open source. S2BApp generates files that can be imported into Snap and Scratch, but only Scratch 2.0 is supported and the current web app doesn't work with these blocks.
Describe alternatives you've considered
- An alternative would be to create custom Blockly blocks and package blockly as a standalone app. This app could export python code that uses the pylgbst library. Likewise Blockpy could be used as well to generate python code from blocks.
Additional context
- In order to communicate with the Boost Robotic hub, a Bluetooth Low Energy connection is required. Some devices have these integrated, but otherwise the user needs an addon dongle such as https://www.silabs.com/products/wireless/bluetooth/bluetooth-low-energy-modules/bled112-bluetooth-smart-dongle
- The pylgbst interface is documented on its github page: https://github.com/undera/pylgbst
- Using the s2bapp and its generated snap/scratch blocks, I was able to determine its supported http interface
The s2bapp starts a server on http://localhost:17327.
The general status of the hub can be requested using
http://localhost:17327/poll
This also tells the s2bapp that "Scratch is Connected"
All commands take the form of
http://localhost:17327/<command>/<parameter_0>/<parameter_n>
Some commands provide a callback like feature using a wait id
http://localhost:17327/<command>/<waitId>/<parameter_0>/<parameter_n>
which can be polled for with this request
http://localhost:17327/poll/<waitId>
This will return the status with a _busy line. if that line contains the command id, the command is still in process.
// Check for absence of : "_busy ... <waitId>;" in
// http://localhost:17327/poll/<waitId>
var busyTextStartPosition=poll.search("_busy");
if (busyTextStartPosition<0) {
return true;
}
var busyText=poll.slice(busyTextStartPosition);
var busyTextEndPosition=busyText.search("\n");
busyText=busyText.slice(0,busyTextEndPosition)+" ";
var waitIdStartPosition=busyText.search(" "+waitId);
return (waitIdStartPosition<0);
s2bapp http interface
/**
* @fn motorOn/<motor>
*
* @brief Turn specified motor on
*
* @param motor is one of [ "motor A", "m*otor B", "motors AB", "motor C", "motor D" ]
*
* @example http://localhost:17327/motorOn/motor A
*/
/**
* @fn motorOff/<motorAll>
*
* @brief Turn specified motor(s) off
*
* @param motorAll is one of [ "motor A", "motor B", "motors AB", "motor C", "motor D", "all motors" ]
*
* @example http://localhost:17327/motorOff/all motors/
*/
/**
* @fn motorOnFor/<waitID>/<motor>/<timeInSeconds>
*
* @brief Turn specified motor on for a number of seconds
*
* @param waitID id to wait for. Polled for with http://localhost:17327/poll/<waitId>
* @param motor is one of [ "motor A", "m*otor B", "motors AB", "motor C", "motor D" ]
* @param timeInSeconds Time in seconds to run selected motor.
*
* @example http://localhost:17327/motorOnFor/1111/motor%20A/3
*/
/**
* @fn startMotorPower/<motor>/<power>
*
* @brief set motor power to percent utilization (0-100)
*
* @param motor is one of [ "motor A", "m*otor B", "motors AB", "motor C", "motor D" ]
* @param power power in percentage (0 to 00)
*
* @example http://localhost:17327/startMotorPower/motor A/100
* @example http://localhost:17327/startMotorPower/motor A/0
*/
/**
* @fn setMotorDirection/<motor>/<motorDirection>
*
* @brief Turn specified motor on
*
* @param motor is one of [ "motor A", "m*otor B", "motors AB", "motor C", "motor D" ]
* @param motorDirection is one of [ "this way", "that way", "other way" ]
*
* @example http://localhost:17327/setMotorDirection/moto A/this way
* @example http://localhost:17327/setMotorDirection/moto A/that way
* @example http://localhost:17327/setMotorDirection/moto A/other way
*/
/**
* @fn motorSteps/<waitID>/<motor>/<fBLR>/<steps>/<power>
*
* @brief turn motor on, forward, backward, left or right, for n steps at given speed
*
* @param waitID id to wait for. Polled for with http://localhost:17327/poll/<waitId>
* @param motor is one of [ "motor A", "m*otor B", "motors AB", "motor C", "motor D" ]
* @param fBLR is one of [ "forwards", "backwards", "left", "right" ]
* @param steps number of steps to take
* @param power power of motor in percent (0-100)
*
* @example http://localhost:17327/motorSteps/1111/motor%20B/forwards/100/50
*/
/**
* @fn motorPosition/<waitID>/<motor>/<position>/<power>
*
* @brief turn motor to a specific position at given speed
*
* @param waitID id to wait for. Polled for with http://localhost:17327/poll/<waitId>
* @param motor is one of [ "motor A", "m*otor B", "motors AB", "motor C", "motor D" ]
* @param position position (in degrees?) to move motor to
* @param power power of motor in percent (0-100)
*
* @example http://localhost:17327/motorPosition/1111/motor B/180/50
*/
/**
* @fn motorResetPosition/<motor>/<position>
*
* @brief reset motor to given position
*
* @param motor is one of [ "motor A", "m*otor B", "motors AB", "motor C", "motor D" ]
* @param position position (in degrees?) to move motor to
*
* @example http://localhost:17327/motorResetPosition/motor B/180
*/
/**
* @fn moveSpeed/<fBLR>/<speedA>/<speedB>
*
* @brief move hub forward, backward, left or right, by moving motors A and B.
*
* If only one speed is passed, it will be used for both motor A and B.
* Otherwise, motor A and motor B will move at the specified speeds.
* Forward or Backward will move A and B in the same direction, but at potentially different speeds.
* Left or Right will move A and B in opposite directions of each other, at their specified speeds.
*
* @param fBLR is one of [ "forwards", "backwards", "left", "right" ]
* @param speedA power of motor A in percent (0-100).
* @param speedB power of motor B in percent (0-100), or speedA if not given.
*
* @example http://localhost:17327/moveSpeed/left/50/50 # moves A and B in alternating directions at 50%
* @example http://localhost:17327/moveSpeed/forward/100/10 # moves A and B forward at different speeds
*/
/**
* @fn moveSteps/<waitID>/<forwardOrBackward>/<steps>/<power>
*
* @brief move hub forward or backward for n steps at given speed
*
* @param waitID id to wait for. Polled for with http://localhost:17327/poll/<waitId>
* @param forwardOrBackward is one of [ "forwards", "backwards" ]
* @param steps number of steps to move motors (A and B)
* @param power power of motor in percent (0-100)
*
* @example http://localhost:17327/moveSteps/1111/forward/100/50
*/
/**
* @fn turnSteps/<waitID>/<leftOrRight>/<steps>/<power>
*
* @brief move hub left or right for n steps at given speed
*
* @param waitID id to wait for. Polled for with http://localhost:17327/poll/<waitId>
* @param leftOrRight is one of [ "left", "right" ]
* @param steps number of steps to move motors (A and B)
* @param power power of motor in percent (0-100)
*
* @example http://localhost:17327/turnSteps/1111/left/243/15
*/
/**
* @fn stopHub
*
* @brief Stop the Hub from whatever it is doing.
*
* @example http://localhost:17327/stopHub
*/
/**
* @fn setLight/<lightColor>
*
* @brief set hub light to given color
*
* @param lightColor is one of [ "pink", "purple", "blue", "sky blue", "teal", "green", "yellow", "orange", "red", "white", "off", "random" ]
*
* @example http://localhost:17327/setLight/pink
*/
/**
* @fn writeName/<hubName>
*
* @brief set hub name
*
* @param hubName String to use for name.
*
* @example http://localhost:17327/writeName/Joes Hub
*/
/**
* @fn poll
*
* @brief poll returns a list of all hub values. These can be parsed to find a particular setting/status.
*
* a line with "_busy <waitId>" indicates that there is an running process.
* waitID indicates that the command associated with that id is still in process.
*
* @code{.js}
* // Check for "_busy <waitId>;" in
* // http://localhost:17327/poll/<waitId>
* var busyTextStartPosition=poll.search("_busy");
* if (busyTextStartPosition<0) {
* return true;
* }
* var busyText=poll.slice(busyTextStartPosition);
* var busyTextEndPosition=busyText.search("\n");
* busyText=busyText.slice(0,busyTextEndPosition)+" ";
* var waitIdStartPosition=busyText.search(" "+waitId);
* return (waitIdStartPosition < 0);
* @endcode
*
* @return sensorA value of sensor A
* @return sensorB value of sensor B
* @return sensorC value of sensor C
* @return sensorD value of sensor D
* @return sensorE value of sensor E
* @return sensorF value of sensor F
* @return tiltx1 88
* @return tilty1 0
* @return current1 244
* @return voltage1 2.9
* @return button1 green hub button, true or false
* @return distance 0-100
* @return color color code of LED. 0-255
* @return tilt 4
* @return isTilted/any true or false
* @return isTilted/up true or false
* @return isTilted/down true or false
* @return isTilted/left true or false
* @return isTilted/right true or false
* @return _busy <waitID> returns wait id of any running process.
* @return _success message indicating s2bapp is succesfully connected to boost robot.
* @return _problem message indicating problem connecting to robot.
*/
Heres a list of all the lists used by the s2bapp interface:
"motorAll": [ "motor A", "motor B", "motors AB", "motor C", "motor D", "all motors" ],
"motorDirection": [ "this way", "that way", "other way" ],
"motor": [ "motor A", "motor B", "motors AB", "motor C", "motor D" ],
"tiltDirAny": [ "any", "up", "down", "left", "right" ],
"lightColor": [ "pink", "purple", "blue", "sky blue", "teal", "green", "yellow", "orange", "red", "white", "off", "random" ],
"forwardOrBackward": [ "forwards", "backwards" ],
"leftOrRight": [ "left", "right" ],
"fBLR": [ "forwards", "backwards", "left", "right" ],
Thank you very much for your detailed description. We have already published two apps, one for IOS and one for Android which are used to communicate between the browser (javascript) and WeDo, which maybe works similar than boost. Do you know if there are open source libraries for native Android and/or IOS available? That would make things much easier.
Won't we just need a wrapper that implements the Bluetooth LE commands and backends for the IOS/Android Bluetooth LE APIs?