ionsystems / tiberius-robot Goto Github PK
View Code? Open in Web Editor NEWRepository for all software modules used by Heriot-Watt University's Tiberius Robot.
Repository for all software modules used by Heriot-Watt University's Tiberius Robot.
There are many aspects of the project that are dependant on the database, to it is top priority to get this fully implemented and working well.
Dependants include:
Features to be implemented
After the above tasks are complete, the database should be easy enough for developers to use.
A python module that provides a simple interface to control Tiberius.
Currently, the idea is to be able to run commands in the following manner, through SSH:
Emulate an smbus network by reading and writing to a local database instead of transmitting an an actual network. This is useful for testing on PC's when you don't have access to Tiberius's sensor network.
smbus_dummy will be used automatically when the platform is not recognised as a raspberry pi.
When attempting to change IP addresses from the Settings page, after changing the IP address, there is no obvious way to save the new value to the settings.
A save button and a dialogue message could be added to make the process clearer.
sqlite_database.py
can be found here: https://github.com/IonSystems/tiberius-robot/blob/master/tiberius/database/sqlite_database.py
The bit that we need to fix is here:
def delete(self, table_name, conditions=None):
self.c.execute(self.__generate_delete(table_name, conditions))
self.conn.commit()
return
and here:
def __generate_delete(self, table_name, conditions):
query = SqlClauses.DELETE.value + " "
query += SqlClauses.FROM.value + " "
query += table_name
if not conditions:
return query
else:
query += " " + self.__generate_conditions(conditions)
return query
If there are no conditions given, then the following output is generated `DELETE FROM test_table'
which doesn't actually do anything...
For now, if no conditions are given, then the following SQL statement should be generated: DELETE * FROM table_name
which is what you would expect the behaviour to be with no conditions.
Allow Tasks to be started, stopped and paused from the web interface.
This will be a useful module to have, and shouldn't require that much work, as there are packages available that will do the hard work for us (https://pypi.python.org/pypi/pyttsx).
I'll start a development branch for this.
Use the RAMPS controller board to control the arm actuators (one servo and three steppers).
A python driver will need to be created in the control module, interfacing with the RAMPS board using serial through a USB cable.
The marlin firmware running on the RAMPS board may also need to be modified, as it is designed for controlling 3D printers, not robot arms.
At the moment we can use the RAMPS board from the chess board, until we get a dedicated one.
The main points to consider when selecting a SLAM library:
There are probably also a lot more things to consider, this is what I can think of at the time of writing. The sooner we commit to a library the better.
I would recommend that this is created as a sub-module within the control module.
This module will handle all robot arm sensing, kinematics algorithms and movement.
This robot_arm
module could be loosely based on a similar module here: https://pypi.python.org/pypi/roboarm/ Although our module will be more powerful, allowing movement using Cartesian coordinates, or by more simply defining the angle of each joint.
Exact requirements for implementation will be completed individually over multiple sprints, and will be defined in separate issues.
Make sure to include an empty __init__.py
file so python knows it's a module.
Also include a README.md file, describing the module's purpose, similar to what I have done above.
On the Sony Xperia Z3 Compact, the the bottom two main menu buttons are off the edge of the screen, the bottom menu item cannot be accessed.
The display should adapt to the screen size, so the app can be used on all android devices with a reasonable screen size.
Create an abstract class with skeleton for basic database manipulation.
Create concrete classes implementing the skeleton for each database type:
This will allow use to easily switch database implementations, and run some benchmarks.
Last years' group interfaced with the GPS in their main autonomy folder as and when required with no library structure. See here.
We want to add GPS support to our control module. The GPS sends us NMEA sentences. Many different types of sentences are transmitted from the GPS, each with a different purpose. Have a look at this link for details.
The GPS is currently configured to send six different types of sentences, we are currently only interested in the GPGGA sentence, but we may be interested in others later in the project.
SELECT | INSERT | ||
---|---|---|---|
int | int | ||
boolean | boolean | ||
varchar(100) | varchar(100) |
Also any other useful benchmarks that come to mind.
Raspberry Pi Camera Live Stream # 1: Pi End
Raspberry Pi Camera Live Stream # 2: Web End
Stream video from the Raspberry Pi Camera using UDP. It would be nice if we could use Python for this, since we use it to do everything else (not the best reasoning I know).
There seems to be a few solutions online that do pretty much what we want(Stack Exchange and Python example)
This stream is going to be received by a socket on the web interface, to display a live(-ish) image so the user can see where they are going.
We want to minimise this as much as possible because the camera will be used to control Tiberius when it is out of sight. We may need to compromise on resolution to keep the bandwidth low. A solution that makes efficient use of bandwidth is preferable, making use of compressi
We would like to be able to install our modules on a Raspberry Pi from a simple setup.py script. This would remove the not so nice sys.path.insert(0, '')
include statements.
The following things must happen at startup:
rtrdb
ServerThat should be it.
SystemD for executing start-up scripts.
We should probably run a different startup script for each daemon/server so they can by easily enabled and disabled individually.
All thoughts are welcome.
The data from the sensors needs to be constantly read and put in the database, which will allow multiple modules to be querying the sensor data at the same time. It will also allow analysis of the data to check its sanity
The new Tiberius design will have optical encoders (http://www.digikey.com/catalog/en/partgroup/hoa0901-and-hoa0902/13300). The encoder will be connected to an mbed or another suitable microcontroller. The microcontroller of choice will have a CAN bus interface.
A Raspberry Pi will provide a desired speed for a motor via the CAN. The mbed/other microcontroller will drive the motor at the desired speed using the optical encoders.
The mbed/other microcontroller will have access to the md05 motor controller, which uses I2C.
The control software will need to be C or C++.
Please tag all testing commits to this issue.
We have a module called control
, this has access to all sensors and actuators. We have many other modules that will need to use control
, and may also me running concurrently. How do we allow access to control without modules interrupting each other?
A queue: We hide the actual control
functions from the other modules and only allow access to the control queue. Because we can have sensors and motors being driven at the same time, we could have multiple queues, one for each piece of hardware that we need to manage, and enqueue from these concurrently.
What about synchronisation? Hmm, yes. Imagine we want to drive to a GPS coordinate and collect LIDAR data. So we do this:
from control.queues import MotorQueue
from control.queues import LIDARQueue
mq = MotorQueue()
lq = LidarQueue()
if __name__ == "__main__":
#Cheating me presuming coordinate is 100 units forward.
mq.add(mq.FORWARD, distance = 100)
lq.add(lq.CAPTURE)
Control would then dequeue from the motor and lidar queue at the same time and they would be executed concurrently. So multiple queues on their own wont work.
Let's roll back to the idea of one queue, this allows us to do one thing at a time, by dequeuing, executing then dequeuing. What if we check what the task is before dequeuing it? This would allow tasks to remain in the correct execution order, and also allow tasks to run concurrently if they can be, by checking if an instance of the particular type of task in question is already running. This will also require locks for each type of task that can be run.
Possible code:
while(True):
if (task = q.readNextTask()): #If there is a next task in the queue
if(resourceAvailable(task['type'])):
task = q.dequeNextTask()
executeTaskInThread(task)
executeTaskInThread()
would take care of the locks for that particular resource, so the while loop could still execute other tasks if the resource is available.
What I have described so far still doesn't answer the original problem, because the move and the LIDAR sense would still be done concurrently. Duh! To be continued...
Use ROS and all this is taken care of.
Create a quick access script that allows the user to execute common test scripts etc. from the root of the repository, rather than hunting for them.
It would be handy to have a style checking script to highlight bad style.
Ideally we would want one that conforms to PEP 8, like PyCharm does.
We could probably incorporate it into quickstart.py
.
Will need a simple Resource created on our Falcon Control API, and a supporting frontend on our Django Web Interface.
The interface should allow for forward and inverse kinematics.
This will be necessary to avoid the awkward sys.path.insert(0, '...')
at top of each file, and allow a simple installation of the sub-packages/modules via distutils. Merry Christmas!
I noticed an unmanageable amount of I2C errors tonight, while testing the control software. I think this is something to do with commit 9bb996b when I may have removed some important delays.
I will test on another installation at some point and see if there is still a problem.
Errors in logging:
2016-01-11 18:15:46,801 - tiberius.control.UltrasonicRangefinder - ERROR - I2C write error 0x73
2016-01-11 18:15:46,880 - tiberius.control.Control - DEBUG - Front Right : True ,Front Centre: True , Front Left: True
2016-01-11 18:15:46,995 - tiberius.control.UltrasonicRangefinder - ERROR - I2C write error 0x73
2016-01-11 18:15:47,076 - tiberius.control.UltrasonicRangefinder - ERROR - I2C write error 0x73
2016-01-11 18:15:47,158 - tiberius.control.UltrasonicRangefinder - ERROR - I2C write error 0x73
2016-01-11 18:15:47,238 - tiberius.control.Control - DEBUG - Front Right : True ,Front Centre: True , Front Left: True
2016-01-11 18:15:47,351 - tiberius.control.UltrasonicRangefinder - ERROR - I2C write error 0x73
2016-01-11 18:15:47,433 - tiberius.control.UltrasonicRangefinder - ERROR - I2C write error 0x73
2016-01-11 18:15:47,515 - tiberius.control.UltrasonicRangefinder - ERROR - I2C write error 0x73
2016-01-11 18:15:47,594 - tiberius.control.Control - DEBUG - Front Right : True ,Front Centre: True , Front Left: True
2016-01-11 18:15:47,708 - tiberius.control.UltrasonicRangefinder - ERROR - I2C write error 0x73
2016-01-11 18:15:47,790 - tiberius.control.UltrasonicRangefinder - ERROR - I2C write error 0x73
2016-01-11 18:15:47,871 - tiberius.control.UltrasonicRangefinder - ERROR - I2C write error 0x73
2016-01-11 18:15:47,951 - tiberius.control.Control - DEBUG - Front Right : True ,Front Centre: True , Front Left: True
2016-01-11 18:15:48,072 - tiberius.control.UltrasonicRangefinder - ERROR - I2C write error 0x73
2016-01-11 18:15:48,154 - tiberius.control.UltrasonicRangefinder - ERROR - I2C write error 0x73
2016-01-11 18:15:48,236 - tiberius.control.UltrasonicRangefinder - ERROR - I2C write error 0x73
2016-01-11 18:15:48,312 - tiberius.control.UltrasonicRangefinder - ERROR - IO error getranging 0x73
2016-01-11 18:15:48,319 - tiberius.control.Control - DEBUG - Front Right : True ,Front Centre: True , Front Left: True
2016-01-11 18:15:48,433 - tiberius.control.UltrasonicRangefinder - ERROR - I2C write error 0x73
2016-01-11 18:15:48,515 - tiberius.control.UltrasonicRangefinder - ERROR - I2C write error 0x73
2016-01-11 18:15:48,597 - tiberius.control.UltrasonicRangefinder - ERROR - I2C write error 0x73
2016-01-11 18:15:48,676 - tiberius.control.Control - DEBUG - Front Right : True ,Front Centre: True , Front Left: True
2016-01-11 18:15:48,790 - tiberius.control.UltrasonicRangefinder - ERROR - I2C write error 0x73
2016-01-11 18:15:48,872 - tiberius.control.UltrasonicRangefinder - ERROR - I2C write error 0x73
2016-01-11 18:15:48,954 - tiberius.control.UltrasonicRangefinder - ERROR - I2C write error 0x73
2016-01-11 18:15:49,033 - tiberius.control.Control - DEBUG - Front Right : True ,Front Centre: True , Front Left: True
2016-01-11 18:15:49,148 - tiberius.control.UltrasonicRangefinder - ERROR - I2C write error 0x73
2016-01-11 18:15:49,229 - tiberius.control.UltrasonicRangefinder - ERROR - I2C write error 0x73
2016-01-11 18:15:49,311 - tiberius.control.UltrasonicRangefinder - ERROR - I2C write error 0x73
2016-01-11 18:15:49,390 - tiberius.control.Control - DEBUG - Front Right : True ,Front Centre: True , Front Left: True
2016-01-11 18:15:49,504 - tiberius.control.UltrasonicRangefinder - ERROR - I2C write error 0x73
2016-01-11 18:15:49,587 - tiberius.control.UltrasonicRangefinder - ERROR - I2C write error 0x73
2016-01-11 18:15:49,668 - tiberius.control.UltrasonicRangefinder - ERROR - I2C write error 0x73
2016-01-11 18:15:49,748 - tiberius.control.Control - DEBUG - Front Right : True ,Front Centre: True , Front Left: True
2016-01-11 18:15:49,862 - tiberius.control.UltrasonicRangefinder - ERROR - I2C write error 0x73
2016-01-11 18:15:49,944 - tiberius.control.UltrasonicRangefinder - ERROR - I2C write error 0x73
2016-01-11 18:15:50,025 - tiberius.control.UltrasonicRangefinder - ERROR - I2C write error 0x73
2016-01-11 18:15:50,105 - tiberius.control.Control - DEBUG - Front Right : True ,Front Centre: True , Front Left: True
2016-01-11 18:15:50,219 - tiberius.control.UltrasonicRangefinder - ERROR - I2C write error 0x73
2016-01-11 18:15:50,300 - tiberius.control.UltrasonicRangefinder - ERROR - I2C write error 0x73
2016-01-11 18:15:50,382 - tiberius.control.UltrasonicRangefinder - ERROR - I2C write error 0x73
2016-01-11 18:15:50,466 - tiberius.control.Control - DEBUG - Front Right : True ,Front Centre: True , Front Left: True
2016-01-11 18:15:50,580 - tiberius.control.UltrasonicRangefinder - ERROR - I2C write error 0x73
2016-01-11 18:15:50,662 - tiberius.control.UltrasonicRangefinder - ERROR - I2C write error 0x73
2016-01-11 18:15:50,743 - tiberius.control.UltrasonicRangefinder - ERROR - I2C write error 0x73
2016-01-11 18:15:50,823 - tiberius.control.Control - DEBUG - Front Right : True ,Front Centre: True , Front Left: True
2016-01-11 18:15:50,937 - tiberius.control.UltrasonicRangefinder - ERROR - I2C write error 0x73
2016-01-11 18:15:51,019 - tiberius.control.UltrasonicRangefinder - ERROR - I2C write error 0x73
2016-01-11 18:15:51,100 - tiberius.control.UltrasonicRangefinder - ERROR - I2C write error 0x73
2016-01-11 18:15:51,179 - tiberius.control.Control - DEBUG - Front Right : True ,Front Centre: True , Front Left: True
2016-01-11 18:15:51,294 - tiberius.control.UltrasonicRangefinder - ERROR - I2C write error 0x73
2016-01-11 18:15:51,375 - tiberius.control.UltrasonicRangefinder - ERROR - I2C write error 0x73
2016-01-11 18:15:51,457 - tiberius.control.UltrasonicRangefinder - ERROR - I2C write error 0x73
2016-01-11 18:15:51,536 - tiberius.control.Control - DEBUG - Front Right : True ,Front Centre: True , Front Left: True
2016-01-11 18:15:51,650 - tiberius.control.UltrasonicRangefinder - ERROR - I2C write error 0x73
2016-01-11 18:15:51,732 - tiberius.control.UltrasonicRangefinder - ERROR - I2C write error 0x73
2016-01-11 18:15:51,813 - tiberius.control.UltrasonicRangefinder - ERROR - I2C write error 0x73
2016-01-11 18:15:51,893 - tiberius.control.Control - DEBUG - Front Right : True ,Front Centre: True , Front Left: True
2016-01-11 18:15:52,007 - tiberius.control.UltrasonicRangefinder - ERROR - I2C write error 0x73
2016-01-11 18:15:52,088 - tiberius.control.UltrasonicRangefinder - ERROR - I2C write error 0x73
2016-01-11 18:15:52,170 - tiberius.control.UltrasonicRangefinder - ERROR - I2C write error 0x73
2016-01-11 18:15:52,249 - tiberius.control.Control - DEBUG - Front Right : True ,Front Centre: True , Front Left: True
2016-01-11 18:15:52,363 - tiberius.control.UltrasonicRangefinder - ERROR - I2C write error 0x73
2016-01-11 18:15:52,446 - tiberius.control.UltrasonicRangefinder - ERROR - I2C write error 0x73
2016-01-11 18:15:52,527 - tiberius.control.UltrasonicRangefinder - ERROR - I2C write error 0x73
2016-01-11 18:15:52,606 - tiberius.control.Control - DEBUG - Front Right : True ,Front Centre: True , Front Left: True
2016-01-11 18:15:52,721 - tiberius.control.UltrasonicRangefinder - ERROR - I2C write error 0x73
2016-01-11 18:15:52,802 - tiberius.control.UltrasonicRangefinder - ERROR - I2C write error 0x73
2016-01-11 18:15:52,883 - tiberius.control.UltrasonicRangefinder - ERROR - I2C write error 0x73
2016-01-11 18:15:52,963 - tiberius.control.Control - DEBUG - Front Right : True ,Front Centre: True , Front Left: True
2016-01-11 18:15:53,078 - tiberius.control.UltrasonicRangefinder - ERROR - I2C write error 0x73
2016-01-11 18:15:53,160 - tiberius.control.UltrasonicRangefinder - ERROR - I2C write error 0x73
2016-01-11 18:15:53,241 - tiberius.control.UltrasonicRangefinder - ERROR - I2C write error 0x73
2016-01-11 18:15:53,078 - tiberius.control.UltrasonicRangefinder - ERROR - I2C write error 0x73
2016-01-11 18:15:53,160 - tiberius.control.UltrasonicRangefinder - ERROR - I2C write error 0x73
2016-01-11 18:15:53,241 - tiberius.control.UltrasonicRangefinder - ERROR - I2C write error 0x73
2016-01-11 18:15:53,321 - tiberius.control.Control - DEBUG - Front Right : True ,Front Centre: True , Front Left: True
I am also wandering why only device 0x73 is giving an error, this could show a hardware issue.
Currently a 'simple' C++ executable is called from a python file, the C++ writes data to a CSV file, and the python reads that CSV file.
We should make this data communication better. I am tempted to port the C++ with a python equivalent.
Support for the following more advanced database features should be added:
We need to knuckle down and design some control loops that actually work. At the moment there are some kicking around in tiberius/testing/test_control.py
ad tiberius/control/control.py
. Ideally they should all be in control.py
.
We also need to take into account different hardware configurations when designing these loops.
Display live LIDAR data in GUI.
This needs to have a way to control everything on any of the tiberius platforms, eg movement, arm control, lighting, camera, etc
To prevent users from accessing the API without valid authentication tokens. Falcon has example code to support this, so our solution will probably be closely based on that.
Example code (https://github.com/falconry/falcon):
class AuthMiddleware(object):
def process_request(self, req, resp):
token = req.get_header('X-Auth-Token')
project = req.get_header('X-Project-ID')
if token is None:
description = ('Please provide an auth token '
'as part of the request.')
raise falcon.HTTPUnauthorized('Auth token required',
description,
href='http://docs.example.com/auth')
if not self._token_is_valid(token, project):
description = ('The provided auth token is not valid. '
'Please request a new token and try again.')
raise falcon.HTTPUnauthorized('Authentication required',
description,
href='http://docs.example.com/auth',
scheme='Token; UUID')
def _token_is_valid(self, token, project):
return True # Suuuuuure it's valid...
We'll need to store a database of valid tokens, and query the database from the control API. The valid tokens will also need to be stored on a database on the web server side, so that the web interface is able to get a valid token to send. Each user of the web interface should have a valid token generated and stored with the user on the web server.
Some sort of synchronisation of the control API database and the web interface database would be really useful here, but not covered in this issue.
For now, we can work with a single authentication token until we have a database synchronisation mechanism.
A background process that monitors a GPIO pin and Ethernet port for a shutdown signal. The daemon will then execute shutdown -h now
to provide a soft power off.
This daemon is to provide a simple interface for safely turning off a Raspberry Pi.
Once this daemon is implemented, a new shutdown switch could be designed for Tiberius, that sends out a shutdown signal when the off button id pressed, and then cuts power after a the Pi's have been shut down.
The shutdown daemon will also allow other Raspberry Pi's to shutdown others via the TCP interface. This will be useful to the diagnostics module, because it will be able to shutdown faulty devices. This will also be handy for power saving, e.g. The batteries are running low and Tiberius is lost, the power management system can shutdown all unnecessary Pi's to save power for the distress beacon.
I have found a number of resources that you may find useful:
Create a new python file in the navigation module, for our A* implementation.
The world will need to be represented in a grid form, the size of the grid will determine the precision of the path. The width and height of the grid should always be the same (square grid). The size of each square should be easily modified.
An object representing a square should be created to store information about it's weight, GPS location, boolean for goal, boolean for start location (these are guesses).
You'll need to decide how big your 2D array of squares is going to be, and how you want to manage it. Do you want a centre square to always represent your current location or do you want to dynamically add more squares to the edge of the array as you approach it?
The algorithm itself: You'll need an accessible function similar to this:
def drive_to_destination(self, lat, long):
# source and destination are Square objects
destination = self.find_square(lat, long)
source = self.find_square(my_lat, my_long)
route = find_path(source, destination)
navigation.followPath(route, 1, 100)
In order to find this square object you'll need some sort of mapping between GPS lat/long and squares. I've just made a find_square()
function that searches through the 2D array of squares for a square that contains the lat and long that you passed in. This can be worked out using the width of the square and the gps location of the centre of the square.
find_path(source, destination)
takes in the source square and the destination square and returns the array of points in the correct format to be passed to navigation.followPath()
. This is where the actual A* algorithm will take place, in find_path(source, destination)
.
When you commit your code it would be nice of you add #47 at the start to attach the commit to this issue.
Please put the actual files there please!!!!
Tag any documentation work here. This could be work on the docs in the /docs
folder or documentation within the source code.
This will all be done in the existing settings module. A configuration file will be created, storing the attributes that define the particular robot, such as IP Addresses and weight. The settings file will be in the format of RFC 822, and be parsed using ConfigParser.
The existing database settings mechanism will be dropped.
This enhancement will allow a user to manually change the configuration of the robot easily. Errors will be generated if the corresponding hardware for the current configuration cannot be found.
When we have a working Raspberry Pi with all the software it requires installed and working correctly, we will create an image of that Pi, so we can easily replicate it, without the need to install any additional software. The firmware images will be included with the official release (https://github.com/IonSystems/tiberius-robot/releases).
There needs to be a table which with boolean values for if a sensor is giving valid data or not.
Each sensor process will check its data to make sure it is valid over a certain time period. If not then it sets its corresponding valid boolean to false.
This is especially needed for the gps in the case that it goes indoors or under a bridge and stops receiving data. If a navigation algorithm was running it needs to know that the gps is no longer giving it information so needs to use other sensors.
Will use solution 2 from http://developer.polyhedra.com/how-to-guides/auto-incrementing-fields.
Should be integrated into polyhedra_database.py.
A python module that contains power a management control code. Will contain algorithms for working out when to power down certain units. You may want to consider adding the following:
There are bound to be a lot more things that you can do that I can't think of at the time of writing.
Should be a daemon that you can run at the start of your class. This module will take the necessary action to make sure nothing goes terribly wrong. For example:
Use ROS
Raspberry Pi Camera Live Stream # 1: Pi End
Raspberry Pi Camera Live Stream # 2: Web End
Add a window to the Manual Control page of the web interface to display the live video stream from a Raspberry Pi on Tiberius.
Depends on #45
python api.py
2016-02-11 16:48:55,341 - tiberius - INFO - Logging Configured
Traceback (most recent call last):
File "api.py", line 9, in <module>
import task_controller
File "/home/cameron/git/tiberius-robot/tiberius/control_api/task_controller.py", line 5, in <module>
from tiberius.control_api.task import *
File "build/bdist.linux-x86_64/egg/tiberius/control_api/task.py", line 3, in <module>
from tiberius.control.control import Control
File "build/bdist.linux-x86_64/egg/tiberius/control/control.py", line 3, in <module>
File "build/bdist.linux-x86_64/egg/tiberius/control/md03.py", line 7, in <module>
File "build/bdist.linux-x86_64/egg/tiberius/smbus_dummy/smbus.py", line 29, in <module>
File "build/bdist.linux-x86_64/egg/tiberius/smbus_dummy/smbus_database.py", line 12, in <module>
File "build/bdist.linux-x86_64/egg/tiberius/database/sqlite_database.py", line 11, in __init__
sqlite3.OperationalError: unable to open database file
I've disabled the database on by api-dev branch until anyone can be bothered fixing it, but I have a feeling we'll just permanently disable the database functionality of smbus_dummy until someone actually needs to use it.
Allow the user to create a mission, by assigning a name, description, permitted users and any other useful information.
This has already been started here: https://github.com/IonSystems/tiberius-robot/tree/master/tiberius/web-interface/missionplanner
This feature depends on #37. Use the basic functions provided by the robot arm driver to create functions that take in Cartesian coordinates, representing a point in space where a specific point on the top of the arm should meet:
def move_arm(x, y, z):
...
You'll need to come up with a accurate-ish mathematical representation of the arm, so that the algorithm is accurate.
You'll need to do some maths to get this working, that's why @AndrewRigg is assigned to it.
These algorithms should be created in a suitable module, control/robotic_arm
I just thought as I was thinking about the diagnostics for Tiberius. It would be awesome if a Pi could manage power.
We could have a Pi/Arduino connected to Ethernet, this device would be connected to lots of relays/transistors to control power to each device on Tiberius. On startup, all devices would have power. The device controlling power obviously will need fixed power, otherwise it could switch itself off.
Any device connected to Ethernet will be able to disable power to other devices or even itself. This will be useful for diagnostics, power saving.
I am sure Euan will say he was thinking this already.
The script needs modified in order to deal with Windows operating systems.
To prevent misuse, e.g. Driving into walls.
The robot should stop before impact with an object.
The robot should continue if an obstacle is sensed behind the robot.
We need to be able to navigate between two GPS way points. This will firstly involve driving directly between two way points with no obstacle avoidance.
After we have a working algorithm for navigating between two points, be can add more complex elements to help with obstacle avoidance.
This issue is only for the basic waypoint navigation function, e.g.
def driveTo(latitude, longitude, speed):
Or something along similar lines.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.