Skip to content

Commit 57d3272

Browse files
authored
Merge pull request #176 from CoderBotOrg/develop
RC6
2 parents 2a22110 + c23ae69 commit 57d3272

File tree

14 files changed

+234
-139
lines changed

14 files changed

+234
-139
lines changed

.circleci/_config.yml

Lines changed: 0 additions & 53 deletions
This file was deleted.

.github/workflows/build_backend.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# This workflow will do a clean install of node dependencies, cache/restore them, build the source code and run tests across different versions of node
22
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
33

4-
name: build CoderBot backend
4+
name: Build CoderBot backend
55

66
on: push
77

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# backend
2-
[![CoderBotOrg](https://circleci.com/gh/CoderBotOrg/backend.svg?style=svg)](https://circleci.com/gh/CoderBotOrg/backend/tree/master)
2+
[![Build CoderBot backend](https://github.com/CoderBotOrg/backend/actions/workflows/build_backend.yml/badge.svg)
33

44
> CoderBot is a RaspberryPI-based programmable robot for educational purposes. Check the [project website](https://www.coderbot.org) for more information.
55
>

coderbot/api.py

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,36 +3,40 @@
33
This file contains every method called by the API defined in v2.yml
44
"""
55

6+
import logging
67
import os
78
import subprocess
8-
import logging
9-
import connexion
10-
from werkzeug.datastructures import Headers
11-
from flask import (request,
12-
send_file,
13-
Response)
14-
import picamera
159
import urllib
10+
1611
import connexion
12+
import picamera
13+
from flask import Response, request, send_file
14+
from werkzeug.datastructures import Headers
1715

18-
from program import ProgramEngine, Program
1916
from config import Config
2017
from activity import Activities
18+
from audio import Audio
2119
from camera import Camera
2220
from cnn.cnn_manager import CNNManager
23-
from musicPackages import MusicPackageManager
24-
from audio import Audio
2521
from coderbotTestUnit import run_test as runCoderbotTestUnit
26-
from coderbot import CoderBot
22+
from musicPackages import MusicPackageManager
23+
from program import Program, ProgramEngine
24+
2725
from balena import Balena
26+
from coderbot import CoderBot
2827

2928
BUTTON_PIN = 16
3029

3130
config = Config.read()
32-
bot = CoderBot.get_instance(
33-
motor_trim_factor=float(config.get("move_motor_trim", 1.0)),
34-
hw_version=config.get("hw_version")
35-
)
31+
bot = CoderBot.get_instance(motor_trim_factor=float(config.get('move_motor_trim', 1.0)),
32+
motor_max_power=int(config.get('motor_max_power', 100)),
33+
motor_min_power=int(config.get('motor_min_power', 0)),
34+
hw_version=config.get('hardware_version'),
35+
pid_params=(float(config.get('pid_kp', 1.0)),
36+
float(config.get('pid_kd', 0.1)),
37+
float(config.get('pid_ki', 0.01)),
38+
float(config.get('pid_max_speed', 200)),
39+
float(config.get('pid_sample_time', 0.01))))
3640
audio_device = Audio.get_instance()
3741
cam = Camera.get_instance()
3842

@@ -125,9 +129,10 @@ def move(body):
125129
def turn(body):
126130
speed=body.get("speed")
127131
elapse=body.get("elapse")
128-
if speed is None or speed == 0:
132+
distance=body.get("distance")
133+
if (speed is None or speed == 0) or (elapse is not None and distance is not None):
129134
return 400
130-
bot.turn(speed=speed, elapse=elapse)
135+
bot.turn(speed=speed, elapse=elapse, distance=distance)
131136
return 200
132137

133138
def takePhoto():

coderbot/coderbot.py

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import os
2121
import sys
2222
import time
23+
from math import copysign
2324
import logging
2425
import pigpio
2526
import sonar
@@ -100,7 +101,7 @@ class CoderBot(object):
100101

101102
# pylint: disable=too-many-instance-attributes
102103

103-
def __init__(self, motor_trim_factor=1.0, hw_version="5"):
104+
def __init__(self, motor_trim_factor=1.0, motor_min_power=0, motor_max_power=100, hw_version="5", pid_params=(0.8, 0.1, 0.01, 200, 0.01)):
104105
try:
105106
self._mpu = mpu.AccelGyroMag()
106107
logging.info("MPU available")
@@ -116,6 +117,8 @@ def __init__(self, motor_trim_factor=1.0, hw_version="5"):
116117
self._cb_elapse = dict()
117118
self._encoder = self.GPIOS.HAS_ENCODER
118119
self._motor_trim_factor = motor_trim_factor
120+
self._motor_min_power = motor_min_power
121+
self._motor_max_power = motor_max_power
119122
self._twin_motors_enc = WheelsAxel(
120123
self.pi,
121124
enable_pin=self.GPIOS.PIN_MOTOR_ENABLE,
@@ -126,7 +129,8 @@ def __init__(self, motor_trim_factor=1.0, hw_version="5"):
126129
right_forward_pin=self.GPIOS.PIN_RIGHT_FORWARD,
127130
right_backward_pin=self.GPIOS.PIN_RIGHT_BACKWARD,
128131
right_encoder_feedback_pin_A=self.GPIOS.PIN_ENCODER_RIGHT_A,
129-
right_encoder_feedback_pin_B=self.GPIOS.PIN_ENCODER_RIGHT_B)
132+
right_encoder_feedback_pin_B=self.GPIOS.PIN_ENCODER_RIGHT_B,
133+
pid_params=pid_params)
130134
self.motor_control = self._dc_enc_motor
131135

132136
self._cb1 = self.pi.callback(self.GPIOS.PIN_PUSHBUTTON, pigpio.EITHER_EDGE, self._cb_button)
@@ -153,21 +157,23 @@ def exit(self):
153157
s.cancel()
154158

155159
@classmethod
156-
def get_instance(cls, motor_trim_factor=1.0, hw_version="5", servo=False):
160+
def get_instance(cls, motor_trim_factor=1.0, motor_max_power=100, motor_min_power=0, hw_version="5", pid_params=(0.8, 0.1, 0.01, 200, 0.01)):
157161
if not cls.the_bot:
158-
cls.the_bot = CoderBot(motor_trim_factor=motor_trim_factor, hw_version=hw_version)
162+
cls.the_bot = CoderBot(motor_trim_factor=motor_trim_factor, motor_max_power= motor_max_power, motor_min_power=motor_min_power, hw_version=hw_version, pid_params=pid_params)
159163
return cls.the_bot
160164

165+
def get_motor_power(self, speed):
166+
return int(copysign(min(max(((self._motor_max_power - self._motor_min_power) * abs(speed) / 100) + self._motor_min_power, self._motor_min_power), self._motor_max_power), speed))
167+
161168
def move(self, speed=100, elapse=None, distance=None):
162-
self._motor_trim_factor = 1.0
163-
speed_left = min(100, max(-100, speed * self._motor_trim_factor))
164-
speed_right = min(100, max(-100, speed / self._motor_trim_factor))
169+
speed_left = speed * self._motor_trim_factor
170+
speed_right = speed / self._motor_trim_factor
165171
self.motor_control(speed_left=speed_left, speed_right=speed_right, time_elapse=elapse, target_distance=distance)
166172

167-
def turn(self, speed=100, elapse=-1):
168-
speed_left = min(100, max(-100, speed * self._motor_trim_factor))
169-
speed_right = -min(100, max(-100, speed / self._motor_trim_factor))
170-
self.motor_control(speed_left=speed_left, speed_right=speed_right, time_elapse=elapse)
173+
def turn(self, speed=100, elapse=None, distance=None):
174+
speed_left = speed * self._motor_trim_factor
175+
speed_right = -speed / self._motor_trim_factor
176+
self.motor_control(speed_left=speed_left, speed_right=speed_right, time_elapse=elapse, target_distance=distance)
171177

172178
def turn_angle(self, speed=100, angle=0):
173179
z = self._mpu.get_gyro()[2]
@@ -225,8 +231,8 @@ def _servo_control(self, pin, angle):
225231
self.pi.set_PWM_dutycycle(pin, duty)
226232

227233
def _dc_enc_motor(self, speed_left=100, speed_right=100, time_elapse=None, target_distance=None):
228-
self._twin_motors_enc.control(power_left=speed_left,
229-
power_right=speed_right,
234+
self._twin_motors_enc.control(power_left=self.get_motor_power(speed_left),
235+
power_right=self.get_motor_power(speed_right),
230236
time_elapse=time_elapse,
231237
target_distance=target_distance)
232238

coderbot/coderbotTestUnit.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,13 @@
1212
If no test was executed on that component, 0 is preserved.
1313
"""
1414
from coderbot import CoderBot
15-
c = CoderBot.get_instance()
1615

1716
# Single components tests
1817

1918
# encoder motors
2019
def __test_encoder():
2120
try:
21+
c = CoderBot.get_instance()
2222
# moving both wheels at speed 100 clockwise
2323
print("moving both wheels at speed 100 clockwise")
2424
assert(c.speed() == 0)

coderbot/main.py

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,10 @@
2222
# Logging configuration
2323
logger = logging.getLogger()
2424
logger.setLevel(os.environ.get("LOGLEVEL", "INFO"))
25-
sh = logging.StreamHandler()
26-
formatter = logging.Formatter('%(message)s')
27-
sh.setFormatter(formatter)
28-
logger.addHandler(sh)
25+
# sh = logging.StreamHandler()
26+
# formatter = logging.Formatter('%(message)s')
27+
# sh.setFormatter(formatter)
28+
# logger.addHandler(sh)
2929

3030
## (Connexion) Flask app configuration
3131

@@ -68,8 +68,7 @@ def run_server():
6868
try:
6969
app.bot_config = Config.read()
7070

71-
bot = CoderBot.get_instance(motor_trim_factor=float(app.bot_config.get('move_motor_trim', 1.0)),
72-
hw_version=app.bot_config.get('hardware_version'))
71+
bot = CoderBot.get_instance()
7372

7473
try:
7574
audio_device = Audio.get_instance()

coderbot/rotary_encoder/motorencoder.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -156,18 +156,19 @@ def rotary_callback(self, tick):
156156

157157
# taking groups of n ticks each
158158
if (self._ticks_counter == 0):
159-
self._start_timer = time() # clock started
159+
self._start_timer = tick # clock started
160160
elif (abs(self._ticks_counter) == self._ticks_threshold):
161-
self._current_timer = time()
162-
elapse = self._current_timer - self._start_timer # calculating time elapse
161+
self._current_timer = tick
162+
elapse = (self._current_timer - self._start_timer) / 1000000.0 # calculating time elapse
163163
# calculating current speed
164164
self._encoder_speed = self._ticks_threshold * self._distance_per_tick / elapse # (mm/s)
165165

166-
self._ticks += tick # updating ticks
166+
self._ticks += 1 # updating ticks
167167

168168
if(abs(self._ticks_counter) < self._ticks_threshold):
169169
self._ticks_counter += 1
170170
else:
171+
self._start_timer = tick # clock started
171172
self._ticks_counter = 0
172173

173174
# updating ticks counter using module

coderbot/rotary_encoder/rotarydecoder.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ def __init__(self, pi, feedback_pin_A, feedback_pin_B, callback):
2727
self._pi.set_pull_up_down(feedback_pin_B, pigpio.PUD_UP)
2828

2929
# callback function on EITHER_EDGE for each pin
30-
self._callback_triggerA = self._pi.callback(feedback_pin_A, pigpio.EITHER_EDGE, self._pulse)
31-
self._callback_triggerB = self._pi.callback(feedback_pin_B, pigpio.EITHER_EDGE, self._pulse)
30+
self._callback_triggerA = self._pi.callback(feedback_pin_A, pigpio.EITHER_EDGE, self._pulseA)
31+
self._callback_triggerB = self._pi.callback(feedback_pin_B, pigpio.EITHER_EDGE, self._pulseA)
3232

3333
self._lastGpio = None
3434

@@ -91,6 +91,9 @@ def _pulse(self, gpio, level, tick):
9191
self._lock.release()
9292
self._callback(direction)
9393

94+
def _pulseA(self, gpio, level, tick):
95+
self._callback(tick)
96+
9497
def cancel(self):
9598

9699
"""

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy