choose our fastproot.so in merge conflict

This commit is contained in:
Roy-vl 2024-02-19 20:03:49 +01:00
commit f027fb2034
11 changed files with 319 additions and 86 deletions

Binary file not shown.

After

(image error) Size: 1 KiB

Binary file not shown.

After

(image error) Size: 1 KiB

Binary file not shown.

After

(image error) Size: 1 KiB

View file

@ -2,4 +2,8 @@ Crosscompile instructions:
* Build docker image with python armv7 installed:
`docker build -t my-image .`
* Use cross to crosscompile:
`cross.exe build --target=armv7-unknown-linux-gnueabihf --release`
`cross.exe build --target=armv7-unknown-linux-gnueabihf --release`
* Move built library to the correct folder:
`cp fastproot/target/armv7-unknown-linux-gnueabihf/release/libfastproot.so ./`
* Move windows binary
`cp fastproot/target/release/fastproot.dll ./fastproot.pyd`

Binary file not shown.

After

(image error) Size: 302 B

Binary file not shown.

Before

(image error) Size: 1,023 B

After

(image error) Size: 1,020 B

View file

@ -1,16 +1,35 @@
use pyo3::prelude::*;
#[derive(Copy, Clone, PartialEq, FromPyObject)]
#[derive(Copy, Clone, FromPyObject, Default, Debug)]
pub struct Point {
x: u8,
y: u8,
color: (u8, u8, u8),
color: [u8; 3],
}
impl PartialEq for Point {
fn eq(&self, other: &Self) -> bool {
self.x == other.x && self.y == other.y
}
}
impl std::fmt::Display for Point {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "({}, {})", self.x, self.y)
}
}
type TuplePoint = (u8,u8, (u8,u8,u8));
impl Point {
pub fn new(x: u8, y: u8) -> Self {
Self {
x, y,
..Default::default()
}
}
fn distance(self, other: Point) -> f64 {
let dx = self.x as f64 - other.x as f64;
let dy = self.y as f64 - other.y as f64;
@ -18,7 +37,20 @@ impl Point {
}
fn into_tuple(&self) -> TuplePoint {
(self.x, self.y, self.color)
(self.x, self.y, (self.color[0], self.color[1], self.color[2]))
}
fn interpolate(self, other: Point, percent: f32) -> Point{
let x = self.x as f32 + ((other.x as f32 - self.x as f32) as f32 * percent);
let y = self.y as f32 + ((other.y as f32 - self.y as f32) as f32 * percent);
let color = (0..3).map(|i| ((1.0 - percent) * self.color[i] as f32 + percent * other.color[i] as f32) as u8).collect::<Vec<_>>();
let color = [
color[0],
color[1],
color[2],
];
Point { x: x as u8, y: y as u8, color }
}
}
@ -35,17 +67,26 @@ pub fn solve(points1: Vec<Point>, points2: Vec<Point>) -> (Vec<usize>, Vec<usize
lsap::solve(points1.len(), points2.len(), &cost_matrix, false).unwrap()
}
pub fn flood_fill(point: Point, mut group: Vec<Point>, points: Vec<Point>) -> Vec<Point> {
pub fn flood_fill(point: Point, mut group: Vec<Point>, points: &[Point]) -> Vec<Point> {
if !group.contains(&point) {
group.push(point);
let neighbors = [(point.x + 1, point.y), (point.x - 1, point.y), (point.x, point.y + 1), (point.x, point.y - 1)];
let neighbors = [
(point.x + 1, point.y),
(point.x - 1, point.y),
(point.x, point.y + 1),
(point.x, point.y - 1),
(point.x + 1, point.y + 1),
(point.x + 1, point.y - 1),
(point.x - 1, point.y + 1),
(point.x - 1, point.y - 1),
];
for neighbor_coords in neighbors {
let neighbor = points.iter().find(|p| p.x == neighbor_coords.0 && p.y == neighbor_coords.1);
if let Some(neighbor) = neighbor {
if !group.contains(&neighbor) {
group = flood_fill(*neighbor, group, points.clone())
group = flood_fill(*neighbor, group, points)
}
}
}
@ -54,78 +95,181 @@ pub fn flood_fill(point: Point, mut group: Vec<Point>, points: Vec<Point>) -> Ve
group
}
// def divide_points_into_groups(points):
// def flood_fill(point, group):
// if point not in group:
// group.append(point)
// neighbors = [(point.x + 1, point.y), (point.x - 1, point.y), (point.x, point.y + 1), (point.x, point.y - 1)]
// for neighbor_coords in neighbors:
// neighbor = next((p for p in points if p.x == neighbor_coords[0] and p.y == neighbor_coords[1]), None)
// if neighbor and neighbor not in group:
// flood_fill(neighbor, group)
//
// groups = []
// remaining_points = [point for point in points if point.x < 64] # Filter points with x < 64
// while remaining_points:
// group = []
// flood_fill(remaining_points[0], group)
// groups.append(group)
// # Remove points in the group from the remaining points
// remaining_points = [point for point in remaining_points if point not in group]
// return groups
#[pyfunction]
pub fn divide_into_groups(points: Vec<Point>) -> Vec<Vec<TuplePoint>> {
let mut groups = vec![];
let mut remaining = points.iter().filter(|p| p.x < 64).collect::<Vec<_>>();
while let Some(&point) = remaining.get(0) {
let group = flood_fill(*point, vec![], points.clone());
groups.push(group.iter().map(|v| v.into_tuple()).collect());
let mut remaining = points.clone().into_iter().filter(|p| p.x < 64).collect::<std::collections::VecDeque<_>>();
while let Some(point) = remaining.pop_front() {
let group = flood_fill(point, vec![], &points);
groups.push(group.clone());
remaining = remaining.into_iter().filter(|p| !group.contains(p)).collect();
}
groups
groups.into_iter().map(|r| r.into_iter().map(|c| c.into_tuple()).collect()).collect()
}
// #[pyfunction]
// fn pair_groups(set_a: Vec<Vec<Point>>, set_b: Vec<Vec<Point>>) -> Vec<(TuplePoint, TuplePoint)> {
// let mut pairs = vec![];
// // Create dictionaries to store bounding boxes for each group
// let mut bounding_boxes_a: std::collections::HashMap::new(); // dict[int, tuple[float, float, float, float]] = {}
// let mut bounding_boxes_a: std::collections::HashMap::new();
pub fn distance(this: (u8, u8), other: (u8, u8)) -> f64 {
let dx = this.0 as f64 - other.0 as f64;
let dy = this.1 as f64 - other.1 as f64;
(dx.powf(2.0) + dy.powf(2.0)).sqrt()
}
// // Calculate bounding boxes for all groups in both sets
// for (i, group) in set_a.iter().chain(set_b).iter().enumerate() {
// let bounding_box = compute_bounding_box(group);
// if i < set_a.len() {
// bounding_boxes_a[i] = bounding_box;
// } else {
// bounding_boxes_b[i - set_a.len()] = bounding_box;
// }
// }
pub fn centroid(points: &[Point]) -> (u8, u8) {
let x = points.iter().fold(0usize, |acc, p| acc + p.x as usize) / points.len();
let y = points.iter().fold(0usize, |acc, p| acc + p.y as usize) / points.len();
(x as u8, y as u8)
}
// // Check for overlaps and determine pairs
// for (i, group_a) in set_a.iter().enumerate() {
// let overlap_detected = false;
// for (j, group_b) in set_b.iter().enenumerate() {
// let bounding_box_a = bounding_boxes_a[i];
// let bounding_box_b = bounding_boxes_b[j];
// if (
// bounding_box_a[0] <= bounding_box_b[1] &&
// bounding_box_a[1] >= bounding_box_b[0] &&
// bounding_box_a[2] <= bounding_box_b[3] &&
// bounding_box_a[3] >= bounding_box_b[2]
// ) {
// pairs.push((group_a, group_b));
// overlap_detected = true;
// break
// }
// }
// if !overlap_detected {
// // Find the nearest neighbor in set B
// let mut nearest_group = set_b[0];
// let mut nearest_value = 0.0f64;
// for val in set_b.iter() {
// if calculate_distance(group_a, val) < nearest_value {
// nearest_group = val;
// }
// }
// pairs.append((group_a, nearest_group));
// }
// }
#[pyfunction]
pub fn pair_groups(smaller: Vec<Vec<Point>>, larger: Vec<Vec<Point>>) -> Vec<(Vec<TuplePoint>, Vec<TuplePoint>)> {
let smaller_center = smaller.iter().map(|v| centroid(v)).collect::<Vec<_>>();
let larger_center = larger.iter().map(|v| centroid(v)).collect::<Vec<_>>();
let mut map = std::collections::HashMap::<usize, Vec<usize>>::new();
// Map each item from centroids2 to an item in centroids1.
for (idx2, coords2) in larger_center.iter().enumerate() {
// Get nearest item in centroids1
let mut nearest_idx = 0;
let mut nearest_dist = f64::MAX;
for (idx1, coords1) in smaller_center.iter().enumerate() {
if distance(*coords1, *coords2) < nearest_dist {
nearest_dist = distance(*coords1, *coords2);
nearest_idx = idx1;
}
}
// now, nearest_idx is the index in centroid1 of the nearest point.
map.entry(nearest_idx).and_modify(|v| v.push(idx2)).or_insert_with(||vec![idx2]);
}
let mut result = vec![];
for (k, indexes) in map {
let mut combined = vec![];
for i in indexes {
combined.extend(larger[i].iter())
}
let key = smaller[k].iter().map(|v| v.into_tuple()).collect();
let combined = combined.into_iter().map(|v: Point| v.into_tuple()).collect();
result.push((key, combined))
}
result
}
#[pyfunction]
pub fn interpolate_point_pairs(pairs: Vec<(Point, Point)>, percent: f32) -> Vec<TuplePoint> {
let mut interpolated_points = vec![];
for (point1, point2) in pairs {
let interpolated_point = point1.interpolate(point2, percent);
if !interpolated_points.contains(&interpolated_point){
interpolated_points.push(interpolated_point);
}
}
interpolated_points.into_iter().map(|v| v.into_tuple()).collect()
}
// pairs
// }
#[pymodule]
fn fastproot(_py: Python<'_>, m: &PyModule) -> PyResult<()> {
m.add_function(wrap_pyfunction!(solve, m)?)?;
m.add_function(wrap_pyfunction!(divide_into_groups, m)?)?;
// m.add_function(wrap_pyfunction!(pair_groups, m)?)?;
m.add_function(wrap_pyfunction!(pair_groups, m)?)?;
m.add_function(wrap_pyfunction!(interpolate_point_pairs, m)?)?;
Ok(())
}
#[cfg(test)]
pub mod tests {
use super::{Point, flood_fill, divide_into_groups, centroid, pair_groups, interpolate_point_pairs};
#[test]
fn should_do_flood_fill() {
let groups = flood_fill(Point::new(1,1), vec![], &vec![
Point::new(1,1),
Point::new(1,2),
Point::new(2,1),
Point::new(3,3),
]);
println!("{groups:?}");
}
#[test]
fn should_divide_into_groups() {
let groups = divide_into_groups(vec![
Point::new(1,1),
Point::new(1,2),
Point::new(2,1),
Point::new(3,3),
Point::new(3,4),
Point::new(4,4)
]);
for (i, g) in groups.iter().enumerate() {
println!("{i}: {g:?}");
}
}
#[test]
fn should_create_centroid() {
let centroid = centroid(&vec![
Point::new(1,1),
Point::new(1,2),
Point::new(2,1),
Point::new(20,10),
]);
println!("{centroid:?}");
}
#[test]
fn should_pair_groups() {
let a = vec![vec![(59, 2), (60, 2), (61, 2), (62, 2), (62, 3)], vec![(15, 8), (16, 8), (17, 8), (18, 8), (19, 8), (20, 8), (21, 8), (22, 8), (23, 8), (24, 8), (25, 8), (26, 8), (27, 8), (27, 9), (28, 9), (29, 9), (30, 9), (30, 10), (31, 10), (31, 11), (29, 10), (26, 9), (25, 9), (24, 9), (23, 9), (22, 9), (21, 9), (20, 9), (19, 9), (18, 9), (17, 9), (16, 9), (15, 9)], vec![(26, 22), (27, 22), (28, 22), (28, 23), (29, 23), (30, 23), (31, 23), (31, 24), (32, 24), (33, 24), (33, 25), (34, 25), (35, 25), (36, 25), (36, 26), (37, 26), (38, 26), (39, 26), (40, 26), (41, 26), (42, 26), (42, 27), (43, 27), (44, 27), (45, 27), (46, 27), (47, 27), (47, 26), (48, 26), (49, 26), (50, 26), (50, 25), (51, 25), (52, 25), (52, 26), (53, 26), (53, 27), (53, 28), (54, 28), (54, 29), (55, 29), (55, 30), (56, 30), (57, 30), (57, 29), (58, 29), (58, 28), (59, 28), (59, 27), (60, 27), (60, 26), (61, 26), (61, 25), (62, 25), (62, 24), (51, 24)]];
let b = vec![vec![(21, 1), (22, 1), (23, 1), (24, 1), (25, 1), (26, 1), (27, 1), (28, 1), (28, 2), (29, 2), (30, 2), (31, 2), (31, 3), (32, 3), (32, 4), (33, 4), (33, 5), (34, 5), (34, 6), (34, 7), (35, 7), (35, 8), (35, 9), (35, 10), (35, 11), (34, 11), (34, 12), (33, 12), (33, 13), (32, 13), (32, 14), (31, 14), (30, 14), (29, 14), (29, 15), (28, 15), (27, 15), (26, 15), (25, 15), (24, 15), (23, 15), (22, 15), (21, 15), (20, 15), (19, 15), (19, 14), (18, 14), (17, 14), (16, 14), (16, 13), (15, 13), (15, 12), (14, 12), (13, 12), (13, 11), (12, 11), (12, 10), (12, 9), (12, 8), (21, 2), (20, 2), (19, 2), (18, 2), (18, 3), (17, 3), (17, 4), (17, 5), (17, 6), (16, 6), (16, 7), (16, 8), (16, 9), (17, 9), (17, 10), (18, 10), (18, 11), (19, 11), (19, 12), (20, 12), (21, 12), (21, 13), (22, 13), (23, 13), (24, 13), (25, 13), (26, 13), (27, 13), (27, 12), (28, 12), (29, 12), (29, 11), (30, 11), (30, 10), (31, 10), (31, 9), (31, 8), (31, 7), (30, 7), (30, 6), (30, 5), (29, 5), (28, 5), (28, 4), (27, 4), (26, 4), (25, 4), (24, 4), (23, 4), (22, 4), (22, 5), (21, 5), (21, 6), (20, 6), (20, 7), (20, 8), (20, 9), (21, 9), (21, 10), (22, 10), (23, 10), (24, 10), (25, 10), (26, 10), (27, 10), (27, 9), (27, 8), (28, 8), (27, 7), (26, 7), (25, 7), (24, 7)], vec![(59, 2), (60, 2), (61, 2), (62, 2), (62, 3)], vec![(26, 22), (27, 22), (28, 22), (28, 23), (29, 23), (30, 23), (31, 23), (31, 24), (32, 24), (33, 24), (33, 25), (34, 25), (35, 25), (36, 25), (36, 26), (37, 26), (38, 26), (39, 26), (40, 26), (41, 26), (42, 26), (42, 27), (43, 27), (44, 27), (45, 27), (46, 27), (47, 27), (47, 26), (48, 26), (49, 26), (50, 26), (50, 25), (51, 25), (52, 25), (52, 26), (53, 26), (53, 27), (53, 28), (54, 28), (54, 29), (55, 29), (55, 30), (56, 30), (57, 30), (57, 29), (58, 29), (58, 28), (59, 28), (59, 27), (60, 27), (60, 26), (61, 26), (61, 25), (62, 25), (62, 24), (51, 24)]];
let a = a.into_iter().map(|r| r.into_iter().map(|(x,y)| Point::new(x,y)).collect()).collect();
let b = b.into_iter().map(|r| r.into_iter().map(|(x,y)| Point::new(x,y)).collect()).collect();
let res = pair_groups(a, b
// vec![
// vec![Point::new(1,1)],
// vec![Point::new(3,3),Point::new(3,4)],
// vec![Point::new(10,10), Point::new(11,11)]
// ],
// vec![
// vec![Point::new(2,2)],
// vec![Point::new(2,5)],
// vec![Point::new(12,12)],
// ]
);
for (i, s) in res {
println!("====> {i:?} => {s:?}");
}
}
}

Binary file not shown.

After

(image error) Size: 575 B

View file

@ -410,8 +410,8 @@ def main():
decision_layer = DecisionLayer(animations, rendering_layer)
# Create and start random blinks interrupts
screen_update_thread = threading.Thread(target=random_blinks)
screen_update_thread.start()
# screen_update_thread = threading.Thread(target=random_blinks)
# screen_update_thread.start()
decision_layer.handle_trigger("boot", "")

View file

@ -31,8 +31,85 @@ animations:
# Additional comments or configuration options for Animation1 can go here.
# For example, you can specify the duration, sound effects, or other details.
- name: blink
- name: set closed
description: Animation to close eyes
loop_count: 1
trigger: Butn_0001_0001
overrideable: true
graphics:
- type: transition
to_file: eyesClosed_neutral.png
duration: 10
- name: set confusion
description: Animation to be confused
loop_count: 1
trigger: Butn_0002_0001
overrideable: true
graphics:
- type: transition
to_file: dizzyFace.png
duration: 10
- name: set angry
description: Animation to be confused
loop_count: 1
trigger: Butn_0003_0001
overrideable: true
graphics:
- type: transition
to_file: angryFace.png
duration: 10
- name: set love
description: Animation for love eyes
loop_count: 1
trigger: Butn_0004_0001
overrideable: true
graphics:
- type: transition
to_file: loveFace.png
duration: 10
- name: reset to continuous blink
description: Animation for blinking
loop_count: 0
trigger: Butn_0004_0001
overrideable: true
graphics:
- type: transition # close the eye from whatever the current state
to_file: eyesClosed_neutral.png
duration: 6
- type: image # hold eye closed
source_file: eyesClosed_neutral.png
duration: 10
- type: transition # open the eye again from being closed
to_file: neutral.png
duration: 6
- type: image # hold eye closed
source_file: neutral.png
duration: 400
- name: blink
description: Animation for a blink
loop_count: 1
trigger: blinkTimer #Button 2 pressed
@ -41,43 +118,38 @@ animations:
graphics:
- type: transition # close the eye from whatever the current state
to_file: dizzyFace.png
duration: 5
to_file: eyesClosed_neutral.png
duration: 6
- type: image # hold eye closed
source_file: dizzyFace.png
source_file: eyesClosed_neutral.png
duration: 10
- type: transition # open the eye again from being closed
to_file: neutral.png
duration: 5
duration: 6
- name: openEye
description: Animation for blinking
loop_count: 1
- name: boot
description: boot with blinking
loop_count: 0
trigger: boot
overrideable: true # blink can be interupted at any time
graphics:
- type: transition # close the eye from whatever the current state
to_file: eyesClosed_neutral.png
duration: 6
- type: image # hold eye closed
source_file: eyesClosed_neutral.png
duration: 1
duration: 10
- type: transition # open the eye again from being closed
to_file: dizzyFace.png
duration: 5
to_file: neutral.png
duration: 6
- name: make dizzy
description: Animation for making dizzy
loop_count: 1
trigger: Butn_0002_0001
overrideable: true # blink can be interupted at any time
graphics:
- type: transition # open the eye again from being closed
to_file: dizzyFace.png
duration: 5
- type: image # hold eye closed
source_file: neutral.png
duration: 400

13
yaml parse test/util.py Normal file
View file

@ -0,0 +1,13 @@
from time import time
def timer(func):
# This function shows the execution time of
# the function object passed
def wrap_func(*args, **kwargs):
t1 = time()
result = func(*args, **kwargs)
t2 = time()
print(f'Function {func.__name__!r} execution: {(t2-t1):.4f}s')
return result
return wrap_func