Skip to content

Commit

Permalink
add more cmap for heatmap debug & add robot dynamics model test in py
Browse files Browse the repository at this point in the history
  • Loading branch information
Mark-tz committed Sep 13, 2024
1 parent 1848cb9 commit eb30ba2
Show file tree
Hide file tree
Showing 10 changed files with 516 additions and 75 deletions.
156 changes: 95 additions & 61 deletions Client/src/field.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,8 @@ Field::Field(QQuickItem *parent)
pixmapPainter.begin(pixmap);
score_pixmap = new QPixmap(QSize(canvasWidth, canvasHeight));
scorePainter.begin(score_pixmap);
score_pixmap_buffer = new QPixmap(QSize(canvasWidth, canvasHeight));
scorebufferPainter.begin(score_pixmap_buffer);
pixmapPainter.setRenderHint(QPainter::Antialiasing, true);
// pixmapPainter.setRenderHint(QPainter::TextAntialiasing, true);
// pixmapPainter.setRenderHint(QPainter::SmoothPixmapTransform, true);
Expand Down Expand Up @@ -542,10 +544,10 @@ void Field::repaint() {//change here!!!!!!!
break;
case 2:
pixmap->fill(COLOR_DARKGREEN);
pixmapPainter.setOpacity(0.3);
score_mutex.lock();
pixmapPainter.drawPixmap(0, 0, *score_pixmap);
score_mutex.unlock();
pixmapPainter.setOpacity(0.4);
score_buffer_mutex.lock();
pixmapPainter.drawPixmap(0, 0, *score_pixmap_buffer);
score_buffer_mutex.unlock();
pixmapPainter.setOpacity(1);
paintInit();
drawMaintainVision(0);
Expand Down Expand Up @@ -828,88 +830,120 @@ float Field::fieldYFromCoordinate(int y) {
return ::ry(y);
}

//// draw score
//Field::Score::Score(){
//}
//void Field::Score::init(){
// for(int i=0;i<COLOR_LEVEL;i++){
// this->size[i] = 0;
// for(int j=0;j<RECT_MAX_SUM;j++){
// this->area[i][j].setSize(QSizeF(::w(RECT_SIZE),::h(RECT_SIZE)));
// }
// }
// //test
// for(int i=-6000;i<6000;i+=RECT_SIZE){
// for(int j=-4500;j<4500;j+=RECT_SIZE){
// auto color = (abs(i/RECT_SIZE) + abs(j/RECT_SIZE))%COLOR_LEVEL;
// if(this->size[color] >= RECT_MAX_SUM)
// continue;
// this->area[color][this->size[color]].moveCenter(QPointF(::x(i),::y(j)));
// this->size[color]++;
// }
// }
//}
void Field::receiveScore() {
socket_score = new QUdpSocket();
socket_score->bind(QHostAddress(ZSS::LOCAL_ADDRESS), 20003);
score_mutex.lock();
score_pixmap->fill(COLOR_DARKGREEN);
score_mutex.unlock();
scorePainter.setPen(Qt::NoPen);
// double c = 0;
// double step = 0.0000001;
while(true) {
std::this_thread::sleep_for(std::chrono::microseconds(500));

// QElapsedTimer timer;
// timer.start();
// for(int i=-6600;i<6600;i+=RECT_SIZE){
// for(int j=-5000;j<5000;j+=RECT_SIZE){
// c += step;
// if(c >= 1 || c <= 0) step = - step;
// c = limitRange(c,0.0,1.0);
// auto r = limitRange(4*c-2,0.0,1.0)*255;
// auto g = limitRange(c<0.5?2*c:4-4*c,0.0,1.0)*255;
// auto b = limitRange(-2*c+1,0.0,1.0)*255;
// scorePainter.setBrush(QColor(r,g,b));
// score_mutex.lock();
// scorePainter.drawRect(QRectF(::x(i),::y(j),::w(RECT_SIZE),::h(RECT_SIZE)));
// score_mutex.unlock();
// }
// }
// qDebug() << "mark fuck : " << timer.nsecsElapsed()/1000000.0 << "millisecond";


parseScores(socket_score);
}
}

QColor cmap(const QString& cm, const float _v);
void Field::parseScores(QUdpSocket* const socket) {
static QByteArray datagram;
static Debug_Heatmap scores;
while (socket->state() == QUdpSocket::BoundState && socket->hasPendingDatagrams()) {
score_mutex.lock();
score_pixmap->fill(COLOR_DARKGREEN);
score_mutex.unlock();
datagram.resize(socket->pendingDatagramSize());
socket->readDatagram(datagram.data(), datagram.size());
scores.ParseFromArray(datagram.data(), datagram.size());
auto size = scores.points_size();
score_mutex.lock();
for(int i = 0; i < size; i++) {
auto score = scores.points(i);
auto color = score.value();
if(color < 0 || color >= COLOR_LEVEL) {
std::cerr << "DEBUG_SCORE : not correct color : " << color << std::endl;
auto c = limitRange(score.value(), 0.0f, 1.0f);
auto size_x = score.x_size();
auto size_y = score.y_size();
auto width = score.size();
if(size_x != size_y) {
std::cerr << "DEBUG_SCORE : not correct size : " << size_x << " " << size_y << std::endl;
continue;
}
auto size = score.p_size();
auto c = limitRange((double)(color) / COLOR_LEVEL, 0.0, 1.0);
auto r = limitRange(4 * c - 2, 0.0, 1.0) * 255;
auto g = limitRange(c < 0.5 ? 2 * c : 4 - 4 * c, 0.0, 1.0) * 255;
auto b = limitRange(-2 * c + 1, 0.0, 1.0) * 255;
scorePainter.setBrush(QColor(r, g, b));
for(int k = 0; k < size; k++) {
auto p = score.p(k);
score_mutex.lock();
scorePainter.drawRect(QRectF(::x(p.x()), ::y(-p.y()), ::w(RECT_SIZE), ::h(-RECT_SIZE)));
score_mutex.unlock();
scorePainter.setBrush(cmap(QString::fromStdString(scores.cmap()),c));
QVector<QRectF> rects;
for(int k = 0; k < size_x; k++) {
auto x = score.x(k);
auto y = score.y(k);
rects.push_back(QRectF(::x(x-width/2), ::y(y+width/2), ::w(width), ::h(-width)));
}
scorePainter.drawRects(rects);
}
score_mutex.unlock();

score_buffer_mutex.lock();
score_pixmap_buffer->fill(COLOR_DARKGREEN);
scorebufferPainter.drawPixmap(0, 0, *score_pixmap);
score_buffer_mutex.unlock();
}
}

QColor cmap(const QString& cm, const float _v){
static auto segValue = [](const float x,const std::map<float, float>& seg) {
float x1 = seg.begin()->first;
float y1 = seg.begin()->second;
float x2 = x1;
float y2 = y1;
for(auto& [k, v] : seg) {
if(k < x) {
x1 = k;
y1 = v;
} else {
x2 = k;
y2 = v;
break;
}
}
if(std::fabs(x2 - x1) <= 1e-9) return y1;
return y1 + (y2 - y1) / (x2 - x1) * (x - x1);
};

float v = std::clamp(_v,0.0f,1.0f);
float r = 0.0f;
float g = 0.0f;
float b = 0.0f;
if(cm == "jet"){
r = segValue(v, {{0.0f, 0.0f}, {0.35f, 0.0f}, {0.65f, 1.0f}, {0.95f, 1.0f}, {1.0f, 0.5f}});
g = segValue(v, {{0.0f, 0.0f}, {0.12f, 0.0f}, {0.37f, 1.0f}, {0.64f, 1.0f}, {0.90f, 0.0f}, {1.0f, 0.0f}});
b = segValue(v, {{0.0f, 0.5f}, {0.1f, 1.0f}, {0.35f, 1.0f}, {0.65f, 0.0f}, {1.0f, 0.0f}});
}else if(cm == "rainbow"){
r = segValue(v, {{0.0f, 0.5f}, {0.25f, 0.0f}, {0.75f, 1.0f}, {1.0f, 1.0f}});
g = -4*(v-0.5f)*(v-0.5) + 1.0f;
b = -v*v + 1.0f;
}else if(cm == "PiYG"){
r = segValue(v, {{ 0.0f, 0.56f},{ 0.1f, 0.78f},{ 0.2f, 0.89f},{ 0.3f, 0.96f},{ 0.4f, 0.98f},{ 0.6f, 0.93f},{ 0.7f, 0.78f},{ 0.8f, 0.54f},{ 0.9f, 0.32f},{ 1.0f, 0.15f},});
g = segValue(v, {{ 0.0f, 0.00f},{ 0.1f, 0.14f},{ 0.2f, 0.52f},{ 0.3f, 0.77f},{ 0.4f, 0.92f},{ 0.6f, 0.96f},{ 0.7f, 0.91f},{ 0.8f, 0.77f},{ 0.9f, 0.59f},{ 1.0f, 0.39f},});
b = segValue(v, {{ 0.0f, 0.32f},{ 0.1f, 0.51f},{ 0.2f, 0.72f},{ 0.3f, 0.88f},{ 0.4f, 0.95f},{ 0.6f, 0.88f},{ 0.7f, 0.62f},{ 0.8f, 0.31f},{ 0.9f, 0.14f},{ 1.0f, 0.10f},});
}else if(cm == "gray"){
r = v;
g = v;
b = v;
}else if(cm == "cool"){
r = v;
g = 1.0f - v;
b = 1.0f;
}else if(cm == "coolwarm"){
r = segValue(v, {{ 0.0f, 0.23f},{ 0.1f, 0.36f},{ 0.2f, 0.51f},{ 0.3f, 0.67f},{ 0.4f, 0.80f},{ 0.6f, 0.92f},{ 0.7f, 0.97f},{ 0.8f, 0.94f},{ 0.9f, 0.85f},{ 1.0f, 0.71f},});
g = segValue(v, {{ 0.0f, 0.30f},{ 0.1f, 0.48f},{ 0.2f, 0.65f},{ 0.3f, 0.78f},{ 0.4f, 0.85f},{ 0.6f, 0.83f},{ 0.7f, 0.72f},{ 0.8f, 0.55f},{ 0.9f, 0.35f},{ 1.0f, 0.02f},});
b = segValue(v, {{ 0.0f, 0.75f},{ 0.1f, 0.90f},{ 0.2f, 0.99f},{ 0.3f, 0.99f},{ 0.4f, 0.93f},{ 0.6f, 0.78f},{ 0.7f, 0.61f},{ 0.8f, 0.44f},{ 0.9f, 0.28f},{ 1.0f, 0.15f},});
}else if(cm == "seismic"){
r = segValue(v, {{ 0.0f, 0.00f},{ 0.2f, 0.00f},{ 0.5f, 1.00f},{ 0.8f, 0.99f},{ 1.0f, 0.50f},});
g = segValue(v, {{ 0.0f, 0.00f},{ 0.2f, 0.00f},{ 0.5f, 0.99f},{ 0.8f, 0.00f},{ 1.0f, 0.00f},});
b = segValue(v, {{ 0.0f, 0.30f},{ 0.2f, 1.00f},{ 0.5f, 0.99f},{ 0.8f, 0.00f},{ 1.0f, 0.00f},});
}else{
r = 4 * v - 2;
g = v < 0.5 ? 2 * v : 4 - 4 * v;
b = -2 * v + 1;
}
return QColor(
std::clamp(r,0.0f,1.0f)*255,
std::clamp(g,0.0f,1.0f)*255,
std::clamp(b,0.0f,1.0f)*255
);
}
13 changes: 3 additions & 10 deletions Client/src/field.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,23 +108,16 @@ private slots:
int ballFocusCount = 0;
// draw Score
private:
const static int RECT_SIZE = 100;// mm
const static int RECT_MAX_SUM = 10000;
const static int COLOR_LEVEL = 256;
// struct Score{
// QRectF area[COLOR_LEVEL][RECT_MAX_SUM];
// int size[COLOR_LEVEL];
// Score();
// void init();
// };
// Score score;
QUdpSocket * socket_score;
void receiveScore();
void parseScores(QUdpSocket* const);

QMutex score_mutex;
QMutex score_buffer_mutex;
QPixmap *score_pixmap;
QPainter scorePainter;
QPixmap *score_pixmap_buffer;
QPainter scorebufferPainter;
};

#endif // __FIELD_H__
89 changes: 89 additions & 0 deletions ZBin/py_playground/rocos/algm/messi.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import numpy as np
from tbkpy.socket.udp import UDPMultiCastReceiver, UDPSender
from tbkpy.socket.plugins import ProtobufParser
from tzcp.ssl.rocos.zss_vision_detection_pb2 import Vision_DetectionFrame
from tzcp.ssl.rocos.zss_debug_pb2 import Debug_Heatmap, Debug_Msgs, Debug_Msg
from tzcp.ssl.rocos.zss_geometry_pb2 import Point
from threading import Event

HEATMAP_COLORS = ["gray", "rainbow", "jet", "PiYG", "cool", "coolwarm", "seismic", "default"]

class Messi:
def __init__(self):
self.signal = Event()
self.receiver = UDPMultiCastReceiver("233.233.233.233", 23333, callback=self.callback, plugin = ProtobufParser(Vision_DetectionFrame))
self.sender = UDPSender(plugin=ProtobufParser(Debug_Heatmap))
self.heatmap_endpoint = ("127.0.0.1", 20003)
self.debug_endpoint = ("127.0.0.1", 20001)

self.heatmap_index = 0
def callback(self, recv):
self.vision = recv[0]
self.signal.set()
def test_heatmap(self):
self.signal.wait()
heatmap = Debug_Heatmap()
# random one
heatmap.cmap = HEATMAP_COLORS[self.heatmap_index]
self.heatmap_index = (self.heatmap_index + 1) % len(HEATMAP_COLORS)
for i in range(91):
heat = Debug_Heatmap.Heat()
y = np.linspace(-3000, 3000, 61)
heat.x.extend([-4500+i*100]*len(y))
heat.y.extend(y)
heat.value = float(i/90)
heat.size = 100 ## mm
heatmap.points.append(heat)
print("pb_size", heatmap.ByteSize())
self.sender.send(heatmap, self.heatmap_endpoint)

debug = Debug_Msgs()

for robot in self.vision.robots_blue:
msg = Debug_Msg()
msg.type = Debug_Msg.Debug_Type.TEXT
msg.text.text = heatmap.cmap
msg.text.pos.x = robot.x
msg.text.pos.y = robot.y
msg.text.size = 120
msg.text.weight = 120
debug.msgs.append(msg)
self.sender.send(debug, self.debug_endpoint)

self.signal.clear()

def main():
import time
messi = Messi()
while True:
time.sleep(1)
messi.test_heatmap()

def get_cmap(cmap_name):
import matplotlib.cm as cm
import matplotlib.pyplot as plt
import numpy as np
value = np.linspace(0, 1, 4)
colors = cm.get_cmap(cmap_name)(value)
# get r g b a
r,g,b,a = colors[:,0], colors[:,1], colors[:,2], colors[:,3]
cc = {"r": r, "g": g, "b": b}
for color, color_value in cc.items():
output = "{"
for i, cv in enumerate(color_value):
output += f"{{ {value[i]:.1f}f, {cv:.2f}f}},"
output += "}"
print(f"{color} = segValue(v, {output});")
# print([f"{c} = segValue(v, {{ {} }});" for c,v in cc.items()])
plt.plot(value, r, 'r')
plt.plot(value, g, 'g')
plt.plot(value, b, 'b')
# plt.plot(value, a, 'k')
plt.show()

if __name__ == "__main__":
import sys
if len(sys.argv) > 2 and sys.argv[1] == "cmap":
get_cmap(sys.argv[2])
exit(0)
main()
Loading

0 comments on commit eb30ba2

Please sign in to comment.