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)