From f76469afc55a16008d61f7c33ea1a3b5923919bd Mon Sep 17 00:00:00 2001 From: Shane Date: Mon, 11 Nov 2019 13:36:24 -0600 Subject: [PATCH 01/34] update messaging_arne to use new c++ in 066 --- selfdrive/messaging_arne/.gitignore | 1 + selfdrive/messaging_arne/Makefile | 63 +++++++ .../__init__.py} | 141 +++++++------- selfdrive/messaging_arne/demo.cc | 50 +++++ selfdrive/messaging_arne/demo.py | 30 +++ selfdrive/messaging_arne/impl_zmq.cc | 173 ++++++++++++++++++ selfdrive/messaging_arne/impl_zmq.hpp | 63 +++++++ selfdrive/messaging_arne/messaging.cc | 51 ++++++ selfdrive/messaging_arne/messaging.hpp | 53 ++++++ selfdrive/messaging_arne/messaging.pxd | 42 +++++ selfdrive/messaging_arne/messaging_pyx.pyx | 104 +++++++++++ .../messaging_arne/messaging_pyx_setup.py | 34 ++++ selfdrive/phantom.py | 2 +- selfdrive/phantom_receiver.py | 2 +- 14 files changed, 745 insertions(+), 64 deletions(-) create mode 100644 selfdrive/messaging_arne/.gitignore create mode 100644 selfdrive/messaging_arne/Makefile rename selfdrive/{messaging_arne.py => messaging_arne/__init__.py} (63%) create mode 100644 selfdrive/messaging_arne/demo.cc create mode 100644 selfdrive/messaging_arne/demo.py create mode 100644 selfdrive/messaging_arne/impl_zmq.cc create mode 100644 selfdrive/messaging_arne/impl_zmq.hpp create mode 100644 selfdrive/messaging_arne/messaging.cc create mode 100644 selfdrive/messaging_arne/messaging.hpp create mode 100644 selfdrive/messaging_arne/messaging.pxd create mode 100644 selfdrive/messaging_arne/messaging_pyx.pyx create mode 100644 selfdrive/messaging_arne/messaging_pyx_setup.py diff --git a/selfdrive/messaging_arne/.gitignore b/selfdrive/messaging_arne/.gitignore new file mode 100644 index 00000000000000..1549b67ca5936e --- /dev/null +++ b/selfdrive/messaging_arne/.gitignore @@ -0,0 +1 @@ +demo diff --git a/selfdrive/messaging_arne/Makefile b/selfdrive/messaging_arne/Makefile new file mode 100644 index 00000000000000..d53e5ece190bee --- /dev/null +++ b/selfdrive/messaging_arne/Makefile @@ -0,0 +1,63 @@ +CXX := clang++ +CC := clang + +BASEDIR = ../.. +PHONELIBS = ../../phonelibs + +CXXFLAGS := -g -O3 -fPIC -std=c++11 -Wall -Wextra -Wshadow -Weffc++ -Wstrict-aliasing -Wpedantic -Werror -MMD -I$(BASEDIR)/selfdrive + +LDLIBS=-lm -lstdc++ -lrt -lpthread + +UNAME_M := $(shell uname -m) + +YAML_FLAGS = -I$(PHONELIBS)/yaml-cpp/include +YAML_LIB = $(abspath $(PHONELIBS)/yaml-cpp/lib/libyaml-cpp.a) + +ifeq ($(UNAME_M),aarch64) + LDFLAGS += -llog -lgnustl_shared + ZMQ_LIBS = /usr/lib/libzmq.a +endif +ifeq ($(UNAME_M),x86_64) + ZMQ_FLAGS = -I$(BASEDIR)/phonelibs/zmq/x64/include + ZMQ_LIBS = $(abspath $(PHONELIBS)/zmq/x64/lib/libzmq.a) + YAML_DIR = $(PHONELIBS)/yaml-cpp/x64/lib/ + YAML_LIB = $(abspath $(PHONELIBS)/yaml-cpp/x64/lib/libyaml-cpp.a) +endif + +ifdef ASAN + CXXFLAGS += -fsanitize=address -fno-omit-frame-pointer + LDFLAGS += -fsanitize=address +endif + +CXXFLAGS += $(ZMQ_FLAGS) $(YAML_FLAGS) + +OBJS := messaging.o impl_zmq.o +DEPS=$(OBJS:.o=.d) + +.PRECIOUS: $(OBJS) +.PHONY: all clean +all: messaging.a messaging_pyx.so + +demo: messaging.a demo.o + $(CC) $(LDFLAGS) $^ $(LDLIBS) -L. -l:messaging.a -o '$@' + +messaging_pyx.so: messaging.a messaging_pyx_setup.py messaging_pyx.pyx messaging.pxd + python3 messaging_pyx_setup.py build_ext --inplace + rm -rf build + rm -f messaging_pyx.cpp + +%.a: $(OBJS) + @echo "[ LINK ] $@" + mkdir -p libs; \ + cd libs; \ + ar -x $(ZMQ_LIBS); \ + ar -x $(YAML_LIB); + + ar rcsD '$@' $^ libs/*.o + rm -r libs + +clean: + @echo "[ CLEAN ]" + rm -rf *.so *.a demo libs $(OBJS) $(DEPS) + +-include $(DEPS) diff --git a/selfdrive/messaging_arne.py b/selfdrive/messaging_arne/__init__.py similarity index 63% rename from selfdrive/messaging_arne.py rename to selfdrive/messaging_arne/__init__.py index 80f9085c2db10b..05eaeec3a5c537 100644 --- a/selfdrive/messaging_arne.py +++ b/selfdrive/messaging_arne/__init__.py @@ -1,110 +1,124 @@ -import zmq +import os +import subprocess + +can_dir = os.path.dirname(os.path.abspath(__file__)) +subprocess.check_call(["make"], cwd=can_dir) +from .messaging_pyx import Context, Poller, SubSocket, PubSocket # pylint: disable=no-name-in-module, import-error from cereal import arne182 as log from common.realtime import sec_since_boot from selfdrive.services import service_list + +context = Context() + def new_message(): dat = log.EventArne182.new_message() dat.logMonoTime = int(sec_since_boot() * 1e9) dat.valid = True return dat -def pub_sock(port, addr="*"): - context = zmq.Context.instance() - sock = context.socket(zmq.PUB) - sock.bind("tcp://%s:%d" % (addr, port)) +def pub_sock(endpoint): + sock = PubSocket() + sock.connect(context, endpoint) return sock -def sub_sock(port, poller=None, addr="127.0.0.1", conflate=False, timeout=None): - context = zmq.Context.instance() - sock = context.socket(zmq.SUB) - if conflate: - sock.setsockopt(zmq.CONFLATE, 1) - sock.connect("tcp://%s:%d" % (addr, port)) - sock.setsockopt(zmq.SUBSCRIBE, b"") +def sub_sock(endpoint, poller=None, addr="127.0.0.1", conflate=False, timeout=None): + sock = SubSocket() + addr = addr.encode('utf8') + sock.connect(context, endpoint, addr, conflate) if timeout is not None: - sock.RCVTIMEO = timeout + sock.setTimeout(timeout) if poller is not None: - poller.register(sock, zmq.POLLIN) + poller.registerSocket(sock) return sock -def drain_sock_raw_poller(poller, sock, wait_for_one=False): - ret = [] - - if wait_for_one: - try: - ret.append(sock.recv()) - except zmq.error.Again: # Thrown when there is timeout on the socket - return ret - - while True: - if not poller.poll(0): - break # Socket has no more messages - - ret.append(sock.recv()) - - return ret - def drain_sock_raw(sock, wait_for_one=False): + """Receive all message currently available on the queue""" ret = [] while 1: - try: - if wait_for_one and len(ret) == 0: - dat = sock.recv() - else: - dat = sock.recv(zmq.NOBLOCK) - ret.append(dat) - except zmq.error.Again: + if wait_for_one and len(ret) == 0: + dat = sock.receive() + else: + dat = sock.receive(non_blocking=True) + + if dat is None: break + + ret.append(dat) + return ret def drain_sock(sock, wait_for_one=False): + """Receive all message currently available on the queue""" ret = [] while 1: - try: - if wait_for_one and len(ret) == 0: - dat = sock.recv() - else: - dat = sock.recv(zmq.NOBLOCK) - dat = log.EventArne182.from_bytes(dat) - ret.append(dat) - except zmq.error.Again: + if wait_for_one and len(ret) == 0: + dat = sock.receive() + else: + dat = sock.receive(non_blocking=True) + + if dat is None: # Timeout hit break + + dat = log.EventArne182.from_bytes(dat) + ret.append(dat) + return ret # TODO: print when we drop packets? def recv_sock(sock, wait=False): + """Same as drain sock, but only returns latest message. Consider using conflate instead.""" dat = None + while 1: - try: - if wait and dat is None: - dat = sock.recv() - else: - dat = sock.recv(zmq.NOBLOCK) - except zmq.error.Again: + if wait and dat is None: + rcv = sock.receive() + else: + rcv = sock.receive(non_blocking=True) + + if rcv is None: # Timeout hit break + + dat = rcv + if dat is not None: dat = log.EventArne182.from_bytes(dat) + return dat def recv_one(sock): - return log.EventArne182.from_bytes(sock.recv()) + dat = sock.receive() + if dat is not None: + dat = log.EventArne182.from_bytes(dat) + return dat def recv_one_or_none(sock): - try: - return log.EventArne182.from_bytes(sock.recv(zmq.NOBLOCK)) - except zmq.error.Again: - return None + dat = sock.receive(non_blocking=True) + if dat is not None: + dat = log.EventArne182.from_bytes(dat) + return dat +def recv_one_retry(sock): + """Keep receiving until we get a message""" + while True: + dat = sock.receive() + if dat is not None: + return log.EventArne182.from_bytes(dat) + +def get_one_can(logcan): + while True: + can = recv_one_retry(logcan) + if len(can.can) > 0: + return can class SubMaster(): def __init__(self, services, ignore_alive=None, addr="127.0.0.1"): - self.poller = zmq.Poller() + self.poller = Poller() self.frame = -1 self.updated = {s : False for s in services} self.rcv_time = {s : 0. for s in services} @@ -124,7 +138,7 @@ def __init__(self, services, ignore_alive=None, addr="127.0.0.1"): for s in services: # TODO: get address automatically from service_list if addr is not None: - self.sock[s] = sub_sock(service_list[s].port, poller=self.poller, addr=addr, conflate=True) + self.sock[s] = sub_sock(s, poller=self.poller, addr=addr, conflate=True) self.freq[s] = service_list[s].frequency data = new_message() @@ -143,7 +157,7 @@ def __getitem__(self, s): def update(self, timeout=-1): msgs = [] - for sock, _ in self.poller.poll(timeout): + for sock in self.poller.poll(timeout): msgs.append(recv_one(sock)) self.update_msgs(sec_since_boot(), msgs) @@ -152,6 +166,9 @@ def update_msgs(self, cur_time, msgs): self.frame += 1 self.updated = dict.fromkeys(self.updated, False) for msg in msgs: + if msg is None: + continue + s = msg.which() self.updated[s] = True self.rcv_time[s] = cur_time @@ -188,10 +205,10 @@ class PubMaster(): def __init__(self, services): self.sock = {} for s in services: - self.sock[s] = pub_sock(service_list[s].port) + self.sock[s] = pub_sock(s) def send(self, s, dat): # accept either bytes or capnp builder if not isinstance(dat, bytes): dat = dat.to_bytes() - self.sock[s].send(dat) + self.sock[s].send(dat) \ No newline at end of file diff --git a/selfdrive/messaging_arne/demo.cc b/selfdrive/messaging_arne/demo.cc new file mode 100644 index 00000000000000..cfdf42209415fc --- /dev/null +++ b/selfdrive/messaging_arne/demo.cc @@ -0,0 +1,50 @@ +#include +#include +#include +#include +#include + +#include "messaging.hpp" +#include "impl_zmq.hpp" + +#define MSGS 1e5 + +int main() { + Context * c = Context::create(); + SubSocket * sub_sock = SubSocket::create(c, "controlsState"); + PubSocket * pub_sock = PubSocket::create(c, "controlsState"); + + char data[8]; + + Poller * poller = Poller::create({sub_sock}); + + auto start = std::chrono::steady_clock::now(); + + for (uint64_t i = 0; i < MSGS; i++){ + *(uint64_t*)data = i; + pub_sock->send(data, 8); + + auto r = poller->poll(100); + + for (auto p : r){ + Message * m = p->receive(); + uint64_t ii = *(uint64_t*)m->getData(); + assert(i == ii); + delete m; + } + } + + + auto end = std::chrono::steady_clock::now(); + double elapsed = std::chrono::duration_cast(end - start).count() / 1e9; + double throughput = ((double) MSGS / (double) elapsed); + std::cout << throughput << " msg/s" << std::endl; + + delete poller; + delete sub_sock; + delete pub_sock; + delete c; + + + return 0; +} diff --git a/selfdrive/messaging_arne/demo.py b/selfdrive/messaging_arne/demo.py new file mode 100644 index 00000000000000..7906a41e203cdf --- /dev/null +++ b/selfdrive/messaging_arne/demo.py @@ -0,0 +1,30 @@ +import time + +from messaging_pyx import Context, Poller, SubSocket, PubSocket # pylint: disable=no-name-in-module, import-error + +MSGS = 1e5 + +if __name__ == "__main__": + c = Context() + sub_sock = SubSocket() + pub_sock = PubSocket() + + sub_sock.connect(c, "controlsState") + pub_sock.connect(c, "controlsState") + + + poller = Poller() + poller.registerSocket(sub_sock) + + t = time.time() + for i in range(int(MSGS)): + bts = i.to_bytes(4, 'little') + pub_sock.send(bts) + + for s in poller.poll(100): + dat = s.receive() + ii = int.from_bytes(dat, 'little') + assert(i == ii) + + dt = time.time() - t + print("%.1f msg/s" % (MSGS / dt)) diff --git a/selfdrive/messaging_arne/impl_zmq.cc b/selfdrive/messaging_arne/impl_zmq.cc new file mode 100644 index 00000000000000..93223e863ac089 --- /dev/null +++ b/selfdrive/messaging_arne/impl_zmq.cc @@ -0,0 +1,173 @@ +#include +#include +#include +#include + +#include + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wshadow" +#include +#pragma GCC diagnostic pop + +#include "impl_zmq.hpp" + +static int get_port(std::string endpoint) { + char * base_dir_ptr = std::getenv("BASEDIR"); + + if (base_dir_ptr == NULL){ + base_dir_ptr = std::getenv("PYTHONPATH"); + } + + assert(base_dir_ptr); + std::string base_dir = base_dir_ptr; + std::string service_list_path = base_dir + "/selfdrive/service_list.yaml"; + YAML::Node service_list = YAML::LoadFile(service_list_path); + + int port = -1; + for (const auto& it : service_list) { + auto name = it.first.as(); + + if (name == endpoint){ + port = it.second[0].as(); + break; + } + } + + if (port == -1){ + std::cout << "Service " << endpoint << " not found" << std::endl; + } + + assert(port >= 0); + return port; +} + +ZMQContext::ZMQContext() { + context = zmq_ctx_new(); +} + +ZMQContext::~ZMQContext() { + zmq_ctx_term(context); +} + +void ZMQMessage::init(size_t sz) { + size = sz; + data = new char[size]; +} + +void ZMQMessage::init(char * d, size_t sz) { + size = sz; + data = new char[size]; + memcpy(data, d, size); +} + +void ZMQMessage::close() { + if (size > 0){ + delete[] data; + } + size = 0; +} + +ZMQMessage::~ZMQMessage() { + this->close(); +} + + +void ZMQSubSocket::connect(Context *context, std::string endpoint, std::string address, bool conflate){ + sock = zmq_socket(context->getRawContext(), ZMQ_SUB); + assert(sock); + + zmq_setsockopt(sock, ZMQ_SUBSCRIBE, "", 0); + + if (conflate){ + int arg = 1; + zmq_setsockopt(sock, ZMQ_CONFLATE, &arg, sizeof(int)); + } + + int reconnect_ivl = 500; + zmq_setsockopt(sock, ZMQ_RECONNECT_IVL_MAX, &reconnect_ivl, sizeof(reconnect_ivl)); + + full_endpoint = "tcp://" + address + ":"; + full_endpoint += std::to_string(get_port(endpoint)); + + std::cout << "ZMQ SUB: " << full_endpoint << std::endl; + + assert(zmq_connect(sock, full_endpoint.c_str()) == 0); +} + + +Message * ZMQSubSocket::receive(bool non_blocking){ + zmq_msg_t msg; + assert(zmq_msg_init(&msg) == 0); + + int flags = non_blocking ? ZMQ_DONTWAIT : 0; + int rc = zmq_msg_recv(&msg, sock, flags); + Message *r = NULL; + + if (rc >= 0){ + // Make a copy to ensure the data is aligned + r = new ZMQMessage; + r->init((char*)zmq_msg_data(&msg), zmq_msg_size(&msg)); + } + + zmq_msg_close(&msg); + return r; +} + +void ZMQSubSocket::setTimeout(int timeout){ + zmq_setsockopt(sock, ZMQ_RCVTIMEO, &timeout, sizeof(int)); +} + +ZMQSubSocket::~ZMQSubSocket(){ + zmq_close(sock); +} + +void ZMQPubSocket::connect(Context *context, std::string endpoint){ + sock = zmq_socket(context->getRawContext(), ZMQ_PUB); + + full_endpoint = "tcp://*:"; + full_endpoint += std::to_string(get_port(endpoint)); + + std::cout << "ZMQ PUB: " << full_endpoint << std::endl; + + assert(zmq_bind(sock, full_endpoint.c_str()) == 0); +} + +int ZMQPubSocket::sendMessage(Message *message){ + return zmq_send(sock, message->getData(), message->getSize(), ZMQ_DONTWAIT); +} + +int ZMQPubSocket::send(char *data, size_t size){ + return zmq_send(sock, data, size, ZMQ_DONTWAIT); +} + +ZMQPubSocket::~ZMQPubSocket(){ + zmq_close(sock); +} + + +void ZMQPoller::registerSocket(SubSocket * socket){ + assert(num_polls + 1 < MAX_POLLERS); + polls[num_polls].socket = socket->getRawSocket(); + polls[num_polls].events = ZMQ_POLLIN; + + sockets.push_back(socket); + num_polls++; +} + +std::vector ZMQPoller::poll(int timeout){ + std::vector r; + + int rc = zmq_poll(polls, num_polls, timeout); + if (rc < 0){ + return r; + } + + for (size_t i = 0; i < num_polls; i++){ + if (polls[i].revents){ + r.push_back(sockets[i]); + } + } + + return r; +} diff --git a/selfdrive/messaging_arne/impl_zmq.hpp b/selfdrive/messaging_arne/impl_zmq.hpp new file mode 100644 index 00000000000000..a40d623e3af849 --- /dev/null +++ b/selfdrive/messaging_arne/impl_zmq.hpp @@ -0,0 +1,63 @@ +#pragma once +#include "messaging.hpp" +#include +#include + +#define MAX_POLLERS 128 + +class ZMQContext : public Context { +private: + void * context = NULL; +public: + ZMQContext(); + void * getRawContext() {return context;} + ~ZMQContext(); +}; + +class ZMQMessage : public Message { +private: + char * data; + size_t size; +public: + void init(size_t size); + void init(char *data, size_t size); + size_t getSize(){return size;} + char * getData(){return data;} + void close(); + ~ZMQMessage(); +}; + +class ZMQSubSocket : public SubSocket { +private: + void * sock; + std::string full_endpoint; +public: + void connect(Context *context, std::string endpoint, std::string address, bool conflate=false); + void setTimeout(int timeout); + void * getRawSocket() {return sock;} + Message *receive(bool non_blocking=false); + ~ZMQSubSocket(); +}; + +class ZMQPubSocket : public PubSocket { +private: + void * sock; + std::string full_endpoint; +public: + void connect(Context *context, std::string endpoint); + int sendMessage(Message *message); + int send(char *data, size_t size); + ~ZMQPubSocket(); +}; + +class ZMQPoller : public Poller { +private: + std::vector sockets; + zmq_pollitem_t polls[MAX_POLLERS]; + size_t num_polls = 0; + +public: + void registerSocket(SubSocket *socket); + std::vector poll(int timeout); + ~ZMQPoller(){}; +}; diff --git a/selfdrive/messaging_arne/messaging.cc b/selfdrive/messaging_arne/messaging.cc new file mode 100644 index 00000000000000..a1178a510872a6 --- /dev/null +++ b/selfdrive/messaging_arne/messaging.cc @@ -0,0 +1,51 @@ +#include "messaging.hpp" +#include "impl_zmq.hpp" + +Context * Context::create(){ + Context * c = new ZMQContext(); + return c; +} + +SubSocket * SubSocket::create(){ + SubSocket * s = new ZMQSubSocket(); + return s; +} + +SubSocket * SubSocket::create(Context * context, std::string endpoint){ + SubSocket *s = SubSocket::create(); + s->connect(context, endpoint, "127.0.0.1"); + + return s; +} + +SubSocket * SubSocket::create(Context * context, std::string endpoint, std::string address){ + SubSocket *s = SubSocket::create(); + s->connect(context, endpoint, address); + + return s; +} + +PubSocket * PubSocket::create(){ + PubSocket * s = new ZMQPubSocket(); + return s; +} + +PubSocket * PubSocket::create(Context * context, std::string endpoint){ + PubSocket *s = PubSocket::create(); + s->connect(context, endpoint); + return s; +} + +Poller * Poller::create(){ + Poller * p = new ZMQPoller(); + return p; +} + +Poller * Poller::create(std::vector sockets){ + Poller * p = Poller::create(); + + for (auto s : sockets){ + p->registerSocket(s); + } + return p; +} diff --git a/selfdrive/messaging_arne/messaging.hpp b/selfdrive/messaging_arne/messaging.hpp new file mode 100644 index 00000000000000..95e34c0d67f4dc --- /dev/null +++ b/selfdrive/messaging_arne/messaging.hpp @@ -0,0 +1,53 @@ +#pragma once +#include +#include +#include + +class Context { +public: + virtual void * getRawContext() = 0; + static Context * create(); + virtual ~Context(){}; +}; + +class Message { +public: + virtual void init(size_t size) = 0; + virtual void init(char * data, size_t size) = 0; + virtual void close() = 0; + virtual size_t getSize() = 0; + virtual char * getData() = 0; + virtual ~Message(){}; +}; + + +class SubSocket { +public: + virtual void connect(Context *context, std::string endpoint, std::string address, bool conflate=false) = 0; + virtual void setTimeout(int timeout) = 0; + virtual Message *receive(bool non_blocking=false) = 0; + virtual void * getRawSocket() = 0; + static SubSocket * create(); + static SubSocket * create(Context * context, std::string endpoint); + static SubSocket * create(Context * context, std::string endpoint, std::string address); + virtual ~SubSocket(){}; +}; + +class PubSocket { +public: + virtual void connect(Context *context, std::string endpoint) = 0; + virtual int sendMessage(Message *message) = 0; + virtual int send(char *data, size_t size) = 0; + static PubSocket * create(); + static PubSocket * create(Context * context, std::string endpoint); + virtual ~PubSocket(){}; +}; + +class Poller { +public: + virtual void registerSocket(SubSocket *socket) = 0; + virtual std::vector poll(int timeout) = 0; + static Poller * create(); + static Poller * create(std::vector sockets); + virtual ~Poller(){}; +}; diff --git a/selfdrive/messaging_arne/messaging.pxd b/selfdrive/messaging_arne/messaging.pxd new file mode 100644 index 00000000000000..5e3da7241544cf --- /dev/null +++ b/selfdrive/messaging_arne/messaging.pxd @@ -0,0 +1,42 @@ +# distutils: language = c++ +#cython: language_level=3 + +from libcpp.string cimport string +from libcpp.vector cimport vector +from libcpp cimport bool + + +cdef extern from "messaging.hpp": + cdef cppclass Context: + @staticmethod + Context * create() + + cdef cppclass Message: + void init(size_t) + void init(char *, size_t) + void close() + size_t getSize() + char *getData() + + + + cdef cppclass SubSocket: + @staticmethod + SubSocket * create() + void connect(Context *, string, string, bool) + Message * receive(bool) + void setTimeout(int) + + + cdef cppclass PubSocket: + @staticmethod + PubSocket * create() + void connect(Context *, string) + int sendMessage(Message *) + int send(char *, size_t) + + cdef cppclass Poller: + @staticmethod + Poller * create() + void registerSocket(SubSocket *) + vector[SubSocket*] poll(int) diff --git a/selfdrive/messaging_arne/messaging_pyx.pyx b/selfdrive/messaging_arne/messaging_pyx.pyx new file mode 100644 index 00000000000000..ff55c310750fd1 --- /dev/null +++ b/selfdrive/messaging_arne/messaging_pyx.pyx @@ -0,0 +1,104 @@ +# distutils: language = c++ +# cython: c_string_encoding=ascii, language_level=3 + +from libcpp.string cimport string +from libcpp cimport bool + + +from messaging cimport Context as cppContext +from messaging cimport SubSocket as cppSubSocket +from messaging cimport PubSocket as cppPubSocket +from messaging cimport Poller as cppPoller +from messaging cimport Message as cppMessage + + +cdef class Context: + cdef cppContext * context + def __cinit__(self): + self.context = cppContext.create() + + def __dealloc__(self): + pass + # Deleting the context will hang if sockets are still active + # TODO: Figure out a way to make sure the context is closed last + # del self.context + + +cdef class Poller: + cdef cppPoller * poller + cdef list sub_sockets + + def __cinit__(self): + self.sub_sockets = [] + self.poller = cppPoller.create() + + def __dealloc__(self): + del self.poller + + def registerSocket(self, SubSocket socket): + self.sub_sockets.append(socket) + self.poller.registerSocket(socket.socket) + + def poll(self, timeout): + sockets = [] + + result = self.poller.poll(timeout) + for s in result: + socket = SubSocket() + socket.setPtr(s) + sockets.append(socket) + + return sockets + +cdef class SubSocket: + cdef cppSubSocket * socket + cdef bool is_owner + + def __cinit__(self): + self.socket = cppSubSocket.create() + self.is_owner = True + + def __dealloc__(self): + if self.is_owner: + del self.socket + + cdef setPtr(self, cppSubSocket * ptr): + if self.is_owner: + del self.socket + + self.is_owner = False + self.socket = ptr + + def connect(self, Context context, string endpoint, string address=b"127.0.0.1", bool conflate=False): + self.socket.connect(context.context, endpoint, address, conflate) + + def setTimeout(self, int timeout): + self.socket.setTimeout(timeout) + + + def receive(self, bool non_blocking=False): + msg = self.socket.receive(non_blocking) + + if msg == NULL: + return None + else: + sz = msg.getSize() + m = msg.getData()[:sz] + del msg + + return m + + +cdef class PubSocket: + cdef cppPubSocket * socket + def __cinit__(self): + self.socket = cppPubSocket.create() + + def __dealloc__(self): + del self.socket + + def connect(self, Context context, string endpoint): + self.socket.connect(context.context, endpoint) + + def send(self, string data): + return self.socket.send(data.c_str(), len(data)) diff --git a/selfdrive/messaging_arne/messaging_pyx_setup.py b/selfdrive/messaging_arne/messaging_pyx_setup.py new file mode 100644 index 00000000000000..53cd73c7d76d3a --- /dev/null +++ b/selfdrive/messaging_arne/messaging_pyx_setup.py @@ -0,0 +1,34 @@ +import os +import subprocess +from distutils.core import Extension, setup # pylint: disable=import-error,no-name-in-module + +from Cython.Build import cythonize + +from common.basedir import BASEDIR +from common.cython_hacks import BuildExtWithoutPlatformSuffix + +sourcefiles = ['messaging_pyx.pyx'] +extra_compile_args = ["-std=c++11"] +libraries = [] +ARCH = subprocess.check_output(["uname", "-m"], encoding='utf8').rstrip() # pylint: disable=unexpected-keyword-arg + +if ARCH == "aarch64": + extra_compile_args += ["-Wno-deprecated-register"] + libraries += ['gnustl_shared'] + +setup(name='CAN parser', + cmdclass={'build_ext': BuildExtWithoutPlatformSuffix}, + ext_modules=cythonize( + Extension( + "messaging_pyx", + language="c++", + sources=sourcefiles, + extra_compile_args=extra_compile_args, + libraries=libraries, + extra_objects=[ + os.path.join(BASEDIR, 'selfdrive', 'messaging', 'messaging.a'), + ] + ) + ), + nthreads=4, +) diff --git a/selfdrive/phantom.py b/selfdrive/phantom.py index 7dda9004383d56..e85b5ad4e90d28 100644 --- a/selfdrive/phantom.py +++ b/selfdrive/phantom.py @@ -11,7 +11,7 @@ class Phantom: def __init__(self, timeout=1.): context = zmq.Context() self.op_params = opParams() - self.phantom_Data_sock = messaging_arne.sub_sock(service_list['phantomData'].port, conflate=True) + self.phantom_Data_sock = messaging_arne.sub_sock('phantomData', conflate=True) self.data = {"status": False, "speed": 0.0} self.last_receive_time = time.time() self.last_phantom_data = {"status": False, "speed": 0.0} diff --git a/selfdrive/phantom_receiver.py b/selfdrive/phantom_receiver.py index db69a95a6b78e4..115897fee20226 100644 --- a/selfdrive/phantom_receiver.py +++ b/selfdrive/phantom_receiver.py @@ -21,7 +21,7 @@ def broadcast_data(self, status, speed, angle, time): self.phantom_data_sock.send(phantom_data.to_bytes()) def enable_phantom(self): - self.phantom_data_sock = messaging_arne.pub_sock(service_list['phantomData'].port) + self.phantom_data_sock = messaging_arne.pub_sock('phantomData') return "ENABLED" # needed to tell the app we're all done with this function def disable_phantom(self): From 7d73d5febd465a74c38d8fa8822eb03f2d16864f Mon Sep 17 00:00:00 2001 From: Shane Date: Mon, 11 Nov 2019 13:48:17 -0600 Subject: [PATCH 02/34] revert to stock --- selfdrive/messaging_arne/__init__.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/selfdrive/messaging_arne/__init__.py b/selfdrive/messaging_arne/__init__.py index 05eaeec3a5c537..f7845cdf62d7ba 100644 --- a/selfdrive/messaging_arne/__init__.py +++ b/selfdrive/messaging_arne/__init__.py @@ -5,7 +5,7 @@ subprocess.check_call(["make"], cwd=can_dir) from .messaging_pyx import Context, Poller, SubSocket, PubSocket # pylint: disable=no-name-in-module, import-error -from cereal import arne182 as log +from cereal import log from common.realtime import sec_since_boot from selfdrive.services import service_list @@ -13,7 +13,7 @@ context = Context() def new_message(): - dat = log.EventArne182.new_message() + dat = log.Event.new_message() dat.logMonoTime = int(sec_since_boot() * 1e9) dat.valid = True return dat @@ -64,7 +64,7 @@ def drain_sock(sock, wait_for_one=False): if dat is None: # Timeout hit break - dat = log.EventArne182.from_bytes(dat) + dat = log.Event.from_bytes(dat) ret.append(dat) return ret @@ -87,20 +87,20 @@ def recv_sock(sock, wait=False): dat = rcv if dat is not None: - dat = log.EventArne182.from_bytes(dat) + dat = log.Event.from_bytes(dat) return dat def recv_one(sock): dat = sock.receive() if dat is not None: - dat = log.EventArne182.from_bytes(dat) + dat = log.Event.from_bytes(dat) return dat def recv_one_or_none(sock): dat = sock.receive(non_blocking=True) if dat is not None: - dat = log.EventArne182.from_bytes(dat) + dat = log.Event.from_bytes(dat) return dat def recv_one_retry(sock): @@ -108,7 +108,7 @@ def recv_one_retry(sock): while True: dat = sock.receive() if dat is not None: - return log.EventArne182.from_bytes(dat) + return log.Event.from_bytes(dat) def get_one_can(logcan): while True: From 9a69234a327b6d2f3b78882259de808a9f76a1a2 Mon Sep 17 00:00:00 2001 From: Shane Date: Mon, 11 Nov 2019 13:55:54 -0600 Subject: [PATCH 03/34] update to messaging_arne --- selfdrive/messaging_arne/__init__.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/selfdrive/messaging_arne/__init__.py b/selfdrive/messaging_arne/__init__.py index f7845cdf62d7ba..05eaeec3a5c537 100644 --- a/selfdrive/messaging_arne/__init__.py +++ b/selfdrive/messaging_arne/__init__.py @@ -5,7 +5,7 @@ subprocess.check_call(["make"], cwd=can_dir) from .messaging_pyx import Context, Poller, SubSocket, PubSocket # pylint: disable=no-name-in-module, import-error -from cereal import log +from cereal import arne182 as log from common.realtime import sec_since_boot from selfdrive.services import service_list @@ -13,7 +13,7 @@ context = Context() def new_message(): - dat = log.Event.new_message() + dat = log.EventArne182.new_message() dat.logMonoTime = int(sec_since_boot() * 1e9) dat.valid = True return dat @@ -64,7 +64,7 @@ def drain_sock(sock, wait_for_one=False): if dat is None: # Timeout hit break - dat = log.Event.from_bytes(dat) + dat = log.EventArne182.from_bytes(dat) ret.append(dat) return ret @@ -87,20 +87,20 @@ def recv_sock(sock, wait=False): dat = rcv if dat is not None: - dat = log.Event.from_bytes(dat) + dat = log.EventArne182.from_bytes(dat) return dat def recv_one(sock): dat = sock.receive() if dat is not None: - dat = log.Event.from_bytes(dat) + dat = log.EventArne182.from_bytes(dat) return dat def recv_one_or_none(sock): dat = sock.receive(non_blocking=True) if dat is not None: - dat = log.Event.from_bytes(dat) + dat = log.EventArne182.from_bytes(dat) return dat def recv_one_retry(sock): @@ -108,7 +108,7 @@ def recv_one_retry(sock): while True: dat = sock.receive() if dat is not None: - return log.Event.from_bytes(dat) + return log.EventArne182.from_bytes(dat) def get_one_can(logcan): while True: From d0992b77bac3bce8b05daa26ba9aaa16d27ab7ed Mon Sep 17 00:00:00 2001 From: Shane Date: Mon, 11 Nov 2019 14:06:55 -0600 Subject: [PATCH 04/34] make sure this is the erroring code --- selfdrive/messaging_arne/Makefile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/selfdrive/messaging_arne/Makefile b/selfdrive/messaging_arne/Makefile index d53e5ece190bee..b34bfbfd3e44d7 100644 --- a/selfdrive/messaging_arne/Makefile +++ b/selfdrive/messaging_arne/Makefile @@ -38,8 +38,7 @@ DEPS=$(OBJS:.o=.d) .PHONY: all clean all: messaging.a messaging_pyx.so -demo: messaging.a demo.o - $(CC) $(LDFLAGS) $^ $(LDLIBS) -L. -l:messaging.a -o '$@' + messaging_pyx.so: messaging.a messaging_pyx_setup.py messaging_pyx.pyx messaging.pxd python3 messaging_pyx_setup.py build_ext --inplace From 328e3bb52a44f9b95244cb0bf6c1880109a697c5 Mon Sep 17 00:00:00 2001 From: Shane Date: Mon, 11 Nov 2019 14:07:28 -0600 Subject: [PATCH 05/34] remove ldlibs for test --- selfdrive/messaging_arne/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/selfdrive/messaging_arne/Makefile b/selfdrive/messaging_arne/Makefile index b34bfbfd3e44d7..1217fc2f167dc6 100644 --- a/selfdrive/messaging_arne/Makefile +++ b/selfdrive/messaging_arne/Makefile @@ -38,7 +38,8 @@ DEPS=$(OBJS:.o=.d) .PHONY: all clean all: messaging.a messaging_pyx.so - +demo: messaging.a demo.o + $(CC) $^ $(LDLIBS) -L. -l:messaging.a -o '$@' messaging_pyx.so: messaging.a messaging_pyx_setup.py messaging_pyx.pyx messaging.pxd python3 messaging_pyx_setup.py build_ext --inplace From 22ca97813e35a379cb1262f96bc4051942a7d1ee Mon Sep 17 00:00:00 2001 From: Shane Date: Mon, 11 Nov 2019 14:10:52 -0600 Subject: [PATCH 06/34] add back --- selfdrive/messaging_arne/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/selfdrive/messaging_arne/Makefile b/selfdrive/messaging_arne/Makefile index 1217fc2f167dc6..d53e5ece190bee 100644 --- a/selfdrive/messaging_arne/Makefile +++ b/selfdrive/messaging_arne/Makefile @@ -39,7 +39,7 @@ DEPS=$(OBJS:.o=.d) all: messaging.a messaging_pyx.so demo: messaging.a demo.o - $(CC) $^ $(LDLIBS) -L. -l:messaging.a -o '$@' + $(CC) $(LDFLAGS) $^ $(LDLIBS) -L. -l:messaging.a -o '$@' messaging_pyx.so: messaging.a messaging_pyx_setup.py messaging_pyx.pyx messaging.pxd python3 messaging_pyx_setup.py build_ext --inplace From e23987dc7d09bbba8c787906e9633b7f2eb3ab83 Mon Sep 17 00:00:00 2001 From: Shane Date: Mon, 11 Nov 2019 14:16:01 -0600 Subject: [PATCH 07/34] is this needed? --- selfdrive/messaging_arne/messaging_pyx.pyx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/selfdrive/messaging_arne/messaging_pyx.pyx b/selfdrive/messaging_arne/messaging_pyx.pyx index ff55c310750fd1..3502d5335ae6eb 100644 --- a/selfdrive/messaging_arne/messaging_pyx.pyx +++ b/selfdrive/messaging_arne/messaging_pyx.pyx @@ -5,11 +5,11 @@ from libcpp.string cimport string from libcpp cimport bool -from messaging cimport Context as cppContext -from messaging cimport SubSocket as cppSubSocket -from messaging cimport PubSocket as cppPubSocket -from messaging cimport Poller as cppPoller -from messaging cimport Message as cppMessage +from messaging_arne cimport Context as cppContext +from messaging_arne cimport SubSocket as cppSubSocket +from messaging_arne cimport PubSocket as cppPubSocket +from messaging_arne cimport Poller as cppPoller +from messaging_arne cimport Message as cppMessage cdef class Context: From 06642aa1e22d82003f6bcbe16a9015b0b3ce308f Mon Sep 17 00:00:00 2001 From: Shane Date: Mon, 11 Nov 2019 14:17:23 -0600 Subject: [PATCH 08/34] nope! --- selfdrive/messaging_arne/messaging_pyx.pyx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/selfdrive/messaging_arne/messaging_pyx.pyx b/selfdrive/messaging_arne/messaging_pyx.pyx index 3502d5335ae6eb..ff55c310750fd1 100644 --- a/selfdrive/messaging_arne/messaging_pyx.pyx +++ b/selfdrive/messaging_arne/messaging_pyx.pyx @@ -5,11 +5,11 @@ from libcpp.string cimport string from libcpp cimport bool -from messaging_arne cimport Context as cppContext -from messaging_arne cimport SubSocket as cppSubSocket -from messaging_arne cimport PubSocket as cppPubSocket -from messaging_arne cimport Poller as cppPoller -from messaging_arne cimport Message as cppMessage +from messaging cimport Context as cppContext +from messaging cimport SubSocket as cppSubSocket +from messaging cimport PubSocket as cppPubSocket +from messaging cimport Poller as cppPoller +from messaging cimport Message as cppMessage cdef class Context: From 926e7152fce03e1bb60b4bfcfbab8e01cbd512f8 Mon Sep 17 00:00:00 2001 From: Shane Date: Mon, 11 Nov 2019 14:18:18 -0600 Subject: [PATCH 09/34] testing --- selfdrive/{messaging => messaging_tmp}/.gitignore | 0 selfdrive/{messaging => messaging_tmp}/Makefile | 0 selfdrive/{messaging => messaging_tmp}/__init__.py | 0 selfdrive/{messaging => messaging_tmp}/demo.cc | 0 selfdrive/{messaging => messaging_tmp}/demo.py | 0 selfdrive/{messaging => messaging_tmp}/impl_zmq.cc | 0 selfdrive/{messaging => messaging_tmp}/impl_zmq.hpp | 0 selfdrive/{messaging => messaging_tmp}/messaging.cc | 0 selfdrive/{messaging => messaging_tmp}/messaging.hpp | 0 selfdrive/{messaging => messaging_tmp}/messaging.pxd | 0 selfdrive/{messaging => messaging_tmp}/messaging_pyx.pyx | 0 selfdrive/{messaging => messaging_tmp}/messaging_pyx_setup.py | 0 12 files changed, 0 insertions(+), 0 deletions(-) rename selfdrive/{messaging => messaging_tmp}/.gitignore (100%) rename selfdrive/{messaging => messaging_tmp}/Makefile (100%) rename selfdrive/{messaging => messaging_tmp}/__init__.py (100%) rename selfdrive/{messaging => messaging_tmp}/demo.cc (100%) rename selfdrive/{messaging => messaging_tmp}/demo.py (100%) rename selfdrive/{messaging => messaging_tmp}/impl_zmq.cc (100%) rename selfdrive/{messaging => messaging_tmp}/impl_zmq.hpp (100%) rename selfdrive/{messaging => messaging_tmp}/messaging.cc (100%) rename selfdrive/{messaging => messaging_tmp}/messaging.hpp (100%) rename selfdrive/{messaging => messaging_tmp}/messaging.pxd (100%) rename selfdrive/{messaging => messaging_tmp}/messaging_pyx.pyx (100%) rename selfdrive/{messaging => messaging_tmp}/messaging_pyx_setup.py (100%) diff --git a/selfdrive/messaging/.gitignore b/selfdrive/messaging_tmp/.gitignore similarity index 100% rename from selfdrive/messaging/.gitignore rename to selfdrive/messaging_tmp/.gitignore diff --git a/selfdrive/messaging/Makefile b/selfdrive/messaging_tmp/Makefile similarity index 100% rename from selfdrive/messaging/Makefile rename to selfdrive/messaging_tmp/Makefile diff --git a/selfdrive/messaging/__init__.py b/selfdrive/messaging_tmp/__init__.py similarity index 100% rename from selfdrive/messaging/__init__.py rename to selfdrive/messaging_tmp/__init__.py diff --git a/selfdrive/messaging/demo.cc b/selfdrive/messaging_tmp/demo.cc similarity index 100% rename from selfdrive/messaging/demo.cc rename to selfdrive/messaging_tmp/demo.cc diff --git a/selfdrive/messaging/demo.py b/selfdrive/messaging_tmp/demo.py similarity index 100% rename from selfdrive/messaging/demo.py rename to selfdrive/messaging_tmp/demo.py diff --git a/selfdrive/messaging/impl_zmq.cc b/selfdrive/messaging_tmp/impl_zmq.cc similarity index 100% rename from selfdrive/messaging/impl_zmq.cc rename to selfdrive/messaging_tmp/impl_zmq.cc diff --git a/selfdrive/messaging/impl_zmq.hpp b/selfdrive/messaging_tmp/impl_zmq.hpp similarity index 100% rename from selfdrive/messaging/impl_zmq.hpp rename to selfdrive/messaging_tmp/impl_zmq.hpp diff --git a/selfdrive/messaging/messaging.cc b/selfdrive/messaging_tmp/messaging.cc similarity index 100% rename from selfdrive/messaging/messaging.cc rename to selfdrive/messaging_tmp/messaging.cc diff --git a/selfdrive/messaging/messaging.hpp b/selfdrive/messaging_tmp/messaging.hpp similarity index 100% rename from selfdrive/messaging/messaging.hpp rename to selfdrive/messaging_tmp/messaging.hpp diff --git a/selfdrive/messaging/messaging.pxd b/selfdrive/messaging_tmp/messaging.pxd similarity index 100% rename from selfdrive/messaging/messaging.pxd rename to selfdrive/messaging_tmp/messaging.pxd diff --git a/selfdrive/messaging/messaging_pyx.pyx b/selfdrive/messaging_tmp/messaging_pyx.pyx similarity index 100% rename from selfdrive/messaging/messaging_pyx.pyx rename to selfdrive/messaging_tmp/messaging_pyx.pyx diff --git a/selfdrive/messaging/messaging_pyx_setup.py b/selfdrive/messaging_tmp/messaging_pyx_setup.py similarity index 100% rename from selfdrive/messaging/messaging_pyx_setup.py rename to selfdrive/messaging_tmp/messaging_pyx_setup.py From 17288274835a4a7c7ed2acd1c8bd01d10be6e7b3 Mon Sep 17 00:00:00 2001 From: Shane Date: Mon, 11 Nov 2019 14:19:55 -0600 Subject: [PATCH 10/34] ahh, this solves it! --- selfdrive/messaging_arne/messaging_pyx_setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/selfdrive/messaging_arne/messaging_pyx_setup.py b/selfdrive/messaging_arne/messaging_pyx_setup.py index 53cd73c7d76d3a..f7fc5a9bde43e1 100644 --- a/selfdrive/messaging_arne/messaging_pyx_setup.py +++ b/selfdrive/messaging_arne/messaging_pyx_setup.py @@ -26,7 +26,7 @@ extra_compile_args=extra_compile_args, libraries=libraries, extra_objects=[ - os.path.join(BASEDIR, 'selfdrive', 'messaging', 'messaging.a'), + os.path.join(BASEDIR, 'selfdrive', 'messaging_arne', 'messaging.a'), ] ) ), From c29996e784e5f50b4f9fea24c74fee7012a61fde Mon Sep 17 00:00:00 2001 From: Shane Date: Mon, 11 Nov 2019 14:22:33 -0600 Subject: [PATCH 11/34] revert back --- selfdrive/{messaging_tmp => messaging}/.gitignore | 0 selfdrive/{messaging_tmp => messaging}/Makefile | 0 selfdrive/{messaging_tmp => messaging}/__init__.py | 0 selfdrive/{messaging_tmp => messaging}/demo.cc | 0 selfdrive/{messaging_tmp => messaging}/demo.py | 0 selfdrive/{messaging_tmp => messaging}/impl_zmq.cc | 0 selfdrive/{messaging_tmp => messaging}/impl_zmq.hpp | 0 selfdrive/{messaging_tmp => messaging}/messaging.cc | 0 selfdrive/{messaging_tmp => messaging}/messaging.hpp | 0 selfdrive/{messaging_tmp => messaging}/messaging.pxd | 0 selfdrive/{messaging_tmp => messaging}/messaging_pyx.pyx | 0 selfdrive/{messaging_tmp => messaging}/messaging_pyx_setup.py | 0 12 files changed, 0 insertions(+), 0 deletions(-) rename selfdrive/{messaging_tmp => messaging}/.gitignore (100%) rename selfdrive/{messaging_tmp => messaging}/Makefile (100%) rename selfdrive/{messaging_tmp => messaging}/__init__.py (100%) rename selfdrive/{messaging_tmp => messaging}/demo.cc (100%) rename selfdrive/{messaging_tmp => messaging}/demo.py (100%) rename selfdrive/{messaging_tmp => messaging}/impl_zmq.cc (100%) rename selfdrive/{messaging_tmp => messaging}/impl_zmq.hpp (100%) rename selfdrive/{messaging_tmp => messaging}/messaging.cc (100%) rename selfdrive/{messaging_tmp => messaging}/messaging.hpp (100%) rename selfdrive/{messaging_tmp => messaging}/messaging.pxd (100%) rename selfdrive/{messaging_tmp => messaging}/messaging_pyx.pyx (100%) rename selfdrive/{messaging_tmp => messaging}/messaging_pyx_setup.py (100%) diff --git a/selfdrive/messaging_tmp/.gitignore b/selfdrive/messaging/.gitignore similarity index 100% rename from selfdrive/messaging_tmp/.gitignore rename to selfdrive/messaging/.gitignore diff --git a/selfdrive/messaging_tmp/Makefile b/selfdrive/messaging/Makefile similarity index 100% rename from selfdrive/messaging_tmp/Makefile rename to selfdrive/messaging/Makefile diff --git a/selfdrive/messaging_tmp/__init__.py b/selfdrive/messaging/__init__.py similarity index 100% rename from selfdrive/messaging_tmp/__init__.py rename to selfdrive/messaging/__init__.py diff --git a/selfdrive/messaging_tmp/demo.cc b/selfdrive/messaging/demo.cc similarity index 100% rename from selfdrive/messaging_tmp/demo.cc rename to selfdrive/messaging/demo.cc diff --git a/selfdrive/messaging_tmp/demo.py b/selfdrive/messaging/demo.py similarity index 100% rename from selfdrive/messaging_tmp/demo.py rename to selfdrive/messaging/demo.py diff --git a/selfdrive/messaging_tmp/impl_zmq.cc b/selfdrive/messaging/impl_zmq.cc similarity index 100% rename from selfdrive/messaging_tmp/impl_zmq.cc rename to selfdrive/messaging/impl_zmq.cc diff --git a/selfdrive/messaging_tmp/impl_zmq.hpp b/selfdrive/messaging/impl_zmq.hpp similarity index 100% rename from selfdrive/messaging_tmp/impl_zmq.hpp rename to selfdrive/messaging/impl_zmq.hpp diff --git a/selfdrive/messaging_tmp/messaging.cc b/selfdrive/messaging/messaging.cc similarity index 100% rename from selfdrive/messaging_tmp/messaging.cc rename to selfdrive/messaging/messaging.cc diff --git a/selfdrive/messaging_tmp/messaging.hpp b/selfdrive/messaging/messaging.hpp similarity index 100% rename from selfdrive/messaging_tmp/messaging.hpp rename to selfdrive/messaging/messaging.hpp diff --git a/selfdrive/messaging_tmp/messaging.pxd b/selfdrive/messaging/messaging.pxd similarity index 100% rename from selfdrive/messaging_tmp/messaging.pxd rename to selfdrive/messaging/messaging.pxd diff --git a/selfdrive/messaging_tmp/messaging_pyx.pyx b/selfdrive/messaging/messaging_pyx.pyx similarity index 100% rename from selfdrive/messaging_tmp/messaging_pyx.pyx rename to selfdrive/messaging/messaging_pyx.pyx diff --git a/selfdrive/messaging_tmp/messaging_pyx_setup.py b/selfdrive/messaging/messaging_pyx_setup.py similarity index 100% rename from selfdrive/messaging_tmp/messaging_pyx_setup.py rename to selfdrive/messaging/messaging_pyx_setup.py From 6a3ba8c8f0c428b30f7557ba40b272466c48153d Mon Sep 17 00:00:00 2001 From: Shane Date: Mon, 11 Nov 2019 14:27:39 -0600 Subject: [PATCH 12/34] remove unused service_list imports, update all messaging_arne calls to latest --- selfdrive/car/toyota/carstate.py | 1 - selfdrive/controls/controlsd.py | 3 +-- selfdrive/controls/lib/pathplanner.py | 3 +-- selfdrive/controls/lib/planner.py | 5 ++--- selfdrive/phantom.py | 1 - selfdrive/phantom_receiver.py | 1 - selfdrive/updated.py | 1 - 7 files changed, 4 insertions(+), 11 deletions(-) diff --git a/selfdrive/car/toyota/carstate.py b/selfdrive/car/toyota/carstate.py index 1abc48e5fd3697..55f70d813e88c4 100644 --- a/selfdrive/car/toyota/carstate.py +++ b/selfdrive/car/toyota/carstate.py @@ -1,6 +1,5 @@ import numpy as np import math -from selfdrive.services import service_list from cereal import arne182 import selfdrive.messaging as messaging from common.numpy_fast import interp diff --git a/selfdrive/controls/controlsd.py b/selfdrive/controls/controlsd.py index 990609aa34dacd..c8f9c1da39dff4 100644 --- a/selfdrive/controls/controlsd.py +++ b/selfdrive/controls/controlsd.py @@ -4,7 +4,6 @@ import capnp import zmq import selfdrive.messaging_arne as messaging_arne -from selfdrive.services import service_list from cereal import car, log, arne182 from common.numpy_fast import clip from common.realtime import sec_since_boot, set_realtime_priority, Ratekeeper, DT_CTRL @@ -461,7 +460,7 @@ def controlsd_thread(sm=None, pm=None, can_sock=None): 'gpsLocation', 'radarState'], ignore_alive=['gpsLocation']) poller = zmq.Poller() - arne182Status = messaging_arne.sub_sock(service_list['arne182Status'].port, poller, conflate=True) # todo: can we use messaging_arne here? + arne182Status = messaging_arne.sub_sock('arne182Status', poller, conflate=True) if can_sock is None: can_timeout = None if os.environ.get('NO_CAN_TIMEOUT', False) else 100 can_sock = messaging.sub_sock('can', timeout=can_timeout) diff --git a/selfdrive/controls/lib/pathplanner.py b/selfdrive/controls/lib/pathplanner.py index 8c4850f8082421..53b04c522c04aa 100644 --- a/selfdrive/controls/lib/pathplanner.py +++ b/selfdrive/controls/lib/pathplanner.py @@ -1,7 +1,6 @@ import math from cereal import arne182 from common.realtime import sec_since_boot -from selfdrive.services import service_list from selfdrive.swaglog import cloudlog from selfdrive.controls.lib.lateral_mpc import libmpc_py from selfdrive.controls.lib.drive_helpers import MPC_COST_LAT @@ -25,7 +24,7 @@ def __init__(self, CP): self.last_cloudlog_t = 0 if not travis: - self.latControl_sock = messaging_arne.pub_sock(service_list['latControl'].port) + self.latControl_sock = messaging_arne.pub_sock('latControl') self.setup_mpc(CP.steerRateCost) self.solution_invalid_cnt = 0 self.path_offset_i = 0.0 diff --git a/selfdrive/controls/lib/planner.py b/selfdrive/controls/lib/planner.py index e4b3b8f804a88b..0fe16acb00ac23 100644 --- a/selfdrive/controls/lib/planner.py +++ b/selfdrive/controls/lib/planner.py @@ -2,7 +2,6 @@ import math from datetime import datetime import time -from selfdrive.services import service_list import zmq import numpy as np from cereal import arne182 @@ -99,8 +98,8 @@ class Planner(): def __init__(self, CP): self.CP = CP self.poller = zmq.Poller() - self.arne182Status = messaging_arne.sub_sock(service_list['arne182Status'].port, poller=self.poller, conflate=True) - self.latcontolStatus = messaging_arne.sub_sock(service_list['latControl'].port, poller=self.poller, conflate=True) + self.arne182Status = messaging_arne.sub_sock('arne182Status', poller=self.poller, conflate=True) + self.latcontolStatus = messaging_arne.sub_sock('latControl', poller=self.poller, conflate=True) self.mpc1 = LongitudinalMpc(1) self.mpc2 = LongitudinalMpc(2) diff --git a/selfdrive/phantom.py b/selfdrive/phantom.py index e85b5ad4e90d28..eed89c399301b2 100644 --- a/selfdrive/phantom.py +++ b/selfdrive/phantom.py @@ -1,6 +1,5 @@ import zmq import selfdrive.messaging_arne as messaging_arne -from selfdrive.services import service_list from common.op_params import opParams import subprocess from common.travis_checker import travis diff --git a/selfdrive/phantom_receiver.py b/selfdrive/phantom_receiver.py index 115897fee20226..09cffc988f238b 100644 --- a/selfdrive/phantom_receiver.py +++ b/selfdrive/phantom_receiver.py @@ -1,4 +1,3 @@ -from selfdrive.services import service_list import selfdrive.messaging_arne as messaging_arne diff --git a/selfdrive/updated.py b/selfdrive/updated.py index 572205ad9c3f67..386b92309787a6 100755 --- a/selfdrive/updated.py +++ b/selfdrive/updated.py @@ -11,7 +11,6 @@ from selfdrive.swaglog import cloudlog from common.op_params import opParams import selfdrive.messaging as messaging -from selfdrive.services import service_list op_params = opParams() From deb28c09a0a34b1008e265b1395b67e0e57683fc Mon Sep 17 00:00:00 2001 From: Shane Date: Mon, 11 Nov 2019 16:14:27 -0600 Subject: [PATCH 13/34] fix for panda version mismatch error --- panda/VERSION | 2 +- panda/board/obj/cert.h | 12 ------------ panda/board/obj/code.bin | Bin 28640 -> 0 bytes panda/board/obj/gitversion.h | 1 - panda/board/obj/main.panda.o | Bin 264024 -> 0 bytes panda/board/obj/panda.bin | Bin 28768 -> 0 bytes panda/board/obj/panda.elf | Bin 217972 -> 0 bytes panda/board/obj/startup_stm32f413xx.o | Bin 7596 -> 0 bytes 8 files changed, 1 insertion(+), 14 deletions(-) delete mode 100644 panda/board/obj/cert.h delete mode 100755 panda/board/obj/code.bin delete mode 100644 panda/board/obj/gitversion.h delete mode 100644 panda/board/obj/main.panda.o delete mode 100644 panda/board/obj/panda.bin delete mode 100755 panda/board/obj/panda.elf delete mode 100644 panda/board/obj/startup_stm32f413xx.o diff --git a/panda/VERSION b/panda/VERSION index 538a65cc825174..4279ff22f4fa77 100644 --- a/panda/VERSION +++ b/panda/VERSION @@ -1 +1 @@ -v1.6.9 \ No newline at end of file +v1.5.9 \ No newline at end of file diff --git a/panda/board/obj/cert.h b/panda/board/obj/cert.h deleted file mode 100644 index ce11e8b4322d05..00000000000000 --- a/panda/board/obj/cert.h +++ /dev/null @@ -1,12 +0,0 @@ -RSAPublicKey debug_rsa_key = {.len = 0x20, - .n0inv = 424155863U, - .n = {2967635737U,1729484964U,2923910269U,896973705U,2756634505U,1709807447U,859352051U,1472485542U,3894793311U,1758995271U,1038644067U,3403716708U,1897604023U,3841462137U,3816219379U,440074165U,3729800853U,260624241U,1851885412U,4004943886U,1292603008U,3542917226U,911436055U,646960542U,732923244U,2088531324U,2245117918U,3785523979U,457179915U,2220748175U,1183724003U,3185822055U}, - .rr = {3273109191U,3469007740U,3022601451U,1950134277U,985405731U,4135629386U,2455447451U,3280986897U,2398786518U,3282545666U,234074194U,9520868U,2034083245U,2050827209U,3952400957U,2761293147U,3022794169U,571779422U,596386776U,1456095933U,1696349762U,1186603127U,877771148U,25300791U,1259288593U,3469483597U,490515539U,1207523392U,1069952767U,3645632153U,103445962U,1631238578U}, - .exponent = 65537, -}; -RSAPublicKey release_rsa_key = {.len = 0x20, - .n0inv = 1360707903U, - .n = {3136311617U,2320862383U,803666948U,3430646816U,580574987U,3438755054U,368561231U,2514628750U,1163918779U,1402283812U,3703279536U,3640319338U,2481729960U,1799009981U,3965904331U,1775854474U,2163541227U,3964480191U,4232838337U,1772169236U,2591977211U,2175464477U,855648893U,1705081629U,387118095U,531497093U,2116518570U,858910171U,1495505556U,1118497527U,3665009874U,3325546900U}, - .rr = {833089023U,2334198892U,2951037656U,3097613940U,1480625656U,2314042190U,767760477U,1330548127U,1851070335U,2943928230U,390126945U,3239825982U,1706845884U,2555293437U,2227978300U,1210679880U,955381365U,1938575352U,3072247641U,9917391U,3743118591U,1096013164U,1945423205U,1015551925U,788452122U,513488935U,145751748U,3046730117U,1184780246U,1616719441U,1144453735U,1858195855U}, - .exponent = 65537, -}; diff --git a/panda/board/obj/code.bin b/panda/board/obj/code.bin deleted file mode 100755 index 046e985d2e60f07e3ebd49f00b5401012cbc94d8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 28640 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 JI$(jZ{|{r$kf{Iw diff --git a/panda/board/obj/gitversion.h b/panda/board/obj/gitversion.h deleted file mode 100644 index 31757e736550e3..00000000000000 --- a/panda/board/obj/gitversion.h +++ /dev/null @@ -1 +0,0 @@ -const uint8_t gitversion[] = "v1.6.9-EON-unknown-DEBUG"; diff --git a/panda/board/obj/main.panda.o b/panda/board/obj/main.panda.o deleted file mode 100644 index 2102b5e690cbd89a1ddc0e528874960244247ac0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 264024 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

OyT34eBy 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 H()0c|4q37h diff --git a/panda/board/obj/panda.bin b/panda/board/obj/panda.bin deleted file mode 100644 index 30b59ed4aae3069a20a8667563388ee8063d11c3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 28768 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%0A`SFo;)fX9V7SB(!YaCxYYXTwc|DkW;TbeVAnYM} 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 OYr3QM_bcca==~cn6)TAV From 761126fc7fb2b8c979debd8bb0a140ef8b5509a6 Mon Sep 17 00:00:00 2001 From: Shane Date: Fri, 15 Nov 2019 16:42:58 -0600 Subject: [PATCH 14/34] compile messaging_arne on first start --- selfdrive/manager.py | 1 + 1 file changed, 1 insertion(+) diff --git a/selfdrive/manager.py b/selfdrive/manager.py index eb06b84181212c..cce85862025a5f 100755 --- a/selfdrive/manager.py +++ b/selfdrive/manager.py @@ -66,6 +66,7 @@ def unblock_stdout(): from selfdrive.swaglog import cloudlog import selfdrive.messaging as messaging +import selfdrive.messaging_arne as messaging_arne # to compile from selfdrive.registration import register from selfdrive.version import version, dirty import selfdrive.crash as crash From b8befdbcee6da86e73eec4a0e0bea17b9218a9e0 Mon Sep 17 00:00:00 2001 From: Shane Date: Sun, 17 Nov 2019 19:25:30 -0600 Subject: [PATCH 15/34] fix for poller not having registerSocket --- selfdrive/controls/controlsd.py | 3 +-- selfdrive/controls/lib/planner.py | 5 ++--- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/selfdrive/controls/controlsd.py b/selfdrive/controls/controlsd.py index c8f9c1da39dff4..f405fe86f10b2e 100644 --- a/selfdrive/controls/controlsd.py +++ b/selfdrive/controls/controlsd.py @@ -459,8 +459,7 @@ def controlsd_thread(sm=None, pm=None, can_sock=None): sm = messaging.SubMaster(['thermal', 'health', 'liveCalibration', 'driverMonitoring', 'plan', 'pathPlan', \ 'gpsLocation', 'radarState'], ignore_alive=['gpsLocation']) - poller = zmq.Poller() - arne182Status = messaging_arne.sub_sock('arne182Status', poller, conflate=True) + arne182Status = messaging_arne.sub_sock('arne182Status', conflate=True) if can_sock is None: can_timeout = None if os.environ.get('NO_CAN_TIMEOUT', False) else 100 can_sock = messaging.sub_sock('can', timeout=can_timeout) diff --git a/selfdrive/controls/lib/planner.py b/selfdrive/controls/lib/planner.py index 0fe16acb00ac23..ca9bffef293038 100644 --- a/selfdrive/controls/lib/planner.py +++ b/selfdrive/controls/lib/planner.py @@ -97,9 +97,8 @@ def limit_accel_in_turns(v_ego, angle_steers, a_target, CP, angle_later): class Planner(): def __init__(self, CP): self.CP = CP - self.poller = zmq.Poller() - self.arne182Status = messaging_arne.sub_sock('arne182Status', poller=self.poller, conflate=True) - self.latcontolStatus = messaging_arne.sub_sock('latControl', poller=self.poller, conflate=True) + self.arne182Status = messaging_arne.sub_sock('arne182Status', conflate=True) + self.latcontolStatus = messaging_arne.sub_sock('latControl', conflate=True) self.mpc1 = LongitudinalMpc(1) self.mpc2 = LongitudinalMpc(2) From ef9e0446d620412e434659eaca2bc6dc0a36eaae Mon Sep 17 00:00:00 2001 From: Shane Date: Sun, 17 Nov 2019 19:43:18 -0600 Subject: [PATCH 16/34] add poller back --- selfdrive/controls/lib/planner.py | 1 + 1 file changed, 1 insertion(+) diff --git a/selfdrive/controls/lib/planner.py b/selfdrive/controls/lib/planner.py index ca9bffef293038..800f94cecd3797 100644 --- a/selfdrive/controls/lib/planner.py +++ b/selfdrive/controls/lib/planner.py @@ -97,6 +97,7 @@ def limit_accel_in_turns(v_ego, angle_steers, a_target, CP, angle_later): class Planner(): def __init__(self, CP): self.CP = CP + self.poller = zmq.Poller() self.arne182Status = messaging_arne.sub_sock('arne182Status', conflate=True) self.latcontolStatus = messaging_arne.sub_sock('latControl', conflate=True) self.mpc1 = LongitudinalMpc(1) From cfe1a381fb8f1aa1774a55317f2a19f6786dbaf0 Mon Sep 17 00:00:00 2001 From: Shane Date: Mon, 18 Nov 2019 13:57:45 -0600 Subject: [PATCH 17/34] make values negative --- selfdrive/controls/lib/long_mpc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/selfdrive/controls/lib/long_mpc.py b/selfdrive/controls/lib/long_mpc.py index 4c0c2e095ea0ee..e153ae4316a6d6 100644 --- a/selfdrive/controls/lib/long_mpc.py +++ b/selfdrive/controls/lib/long_mpc.py @@ -120,7 +120,7 @@ def smooth_follow(self): # in m/s TR = interp(self.v_ego, x, y) if self.v_lead is not None: # since the new mpc now handles braking nicely, simplify mods - x = [2.68, 2.1, 1.26, 0.61, 0, 0.61, 1.26, 2.1, 2.68] # relative velocity values todo: add back negative values to get farther away from lead when it's slower + x = [-2.68, -2.1, -1.26, -0.61, 0, 0.61, 1.26, 2.1, 2.68] # relative velocity values y = [0.272, 0.154, 0.053, 0.017, 0, -0.017, -0.053, -0.154, -0.272] # modification values TR_mod = interp(self.v_lead - self.v_ego, x, y) # quicker acceleration/don't brake when lead is overtaking From db361e3d7fdc13af2a973a615ce59057cbb38ba7 Mon Sep 17 00:00:00 2001 From: Shane Date: Mon, 18 Nov 2019 14:11:25 -0600 Subject: [PATCH 18/34] updates to long_mpc --- selfdrive/controls/lib/long_mpc.py | 56 +++++++++++------------------- 1 file changed, 21 insertions(+), 35 deletions(-) diff --git a/selfdrive/controls/lib/long_mpc.py b/selfdrive/controls/lib/long_mpc.py index e153ae4316a6d6..cd9e0155f1377e 100644 --- a/selfdrive/controls/lib/long_mpc.py +++ b/selfdrive/controls/lib/long_mpc.py @@ -32,9 +32,9 @@ def __init__(self, mpc_id): self.car_data = {"lead_vels": [], "traffic_vels": []} self.mpc_frame = 0 # idea thanks to kegman self.last_time = None - self.v_lead = None - self.x_lead = None + self.lead_data = {'v_lead': None, 'x_lead': None, 'a_lead': None, 'status': False} self.df_frame = 0 + self.rate = 20 self.phantom = Phantom(timeout=1.) self.last_cloudlog_t = 0.0 @@ -72,23 +72,23 @@ def set_cur_state(self, v, a): def get_acceleration(self): # calculate acceleration to generate more accurate following distances a = 0.0 - if len(self.car_data["lead_vels"]) > self.calc_rate(2): + if len(self.car_data["lead_vels"]) > self.rate * 2: num = (self.car_data["lead_vels"][-1] - self.car_data["lead_vels"][0]) - den = len(self.car_data["lead_vels"]) / self.calc_rate() + den = len(self.car_data["lead_vels"]) / self.rate if den > 0: a = num / float(den) return a def save_car_data(self): - if self.v_lead is not None: - while len(self.car_data["lead_vels"]) > self.calc_rate(3): # 3 seconds + if self.lead_data['v_lead'] is not None: + while len(self.car_data["lead_vels"]) > self.rate * 3: # 3 seconds del self.car_data["lead_vels"][0] - self.car_data["lead_vels"].append(self.v_lead) + self.car_data["lead_vels"].append(self.lead_data['v_lead']) - if self.mpc_frame >= self.calc_rate(): # add to traffic list every second so we're not working with a huge list + if self.mpc_frame >= self.rate: # add to traffic list every second so we're not working with a huge list while len(self.car_data["traffic_vels"]) > 180: # 3 minutes of traffic logging del self.car_data["traffic_vels"][0] - self.car_data["traffic_vels"].append(self.v_lead) + self.car_data["traffic_vels"].append(self.lead_data['v_lead']) self.mpc_frame = 0 # reset every second self.mpc_frame += 1 # increment every frame @@ -119,14 +119,15 @@ def smooth_follow(self): # in m/s y = [1.8, interp(x[1], x_vel, y_mod)] TR = interp(self.v_ego, x, y) - if self.v_lead is not None: # since the new mpc now handles braking nicely, simplify mods + if self.lead_data['v_lead'] is not None: # since the new mpc now handles braking nicely, simplify mods x = [-2.68, -2.1, -1.26, -0.61, 0, 0.61, 1.26, 2.1, 2.68] # relative velocity values y = [0.272, 0.154, 0.053, 0.017, 0, -0.017, -0.053, -0.154, -0.272] # modification values - TR_mod = interp(self.v_lead - self.v_ego, x, y) # quicker acceleration/don't brake when lead is overtaking + TR_mod = interp(self.lead_data['v_lead'] - self.v_ego, x, y) # quicker acceleration/don't brake when lead is overtaking - # x = [-1.49, -1.1, -0.67, 0.0, 0.67, 1.1, 1.49] # todo: work on adding this back - # y = [0.056, 0.032, 0.016, 0.0, -0.016, -0.032, -0.056] - # TR_mod += interp(self.get_acceleration(), x, y) # when lead car has been braking over the past 3 seconds, slightly increase TR + x = [-1.49, -1.1, -0.67, 0.0, 0.67, 1.1, 1.49] + y = [0.056, 0.032, 0.016, 0.0, -0.016, -0.032, -0.056] + TR_mod += interp(self.lead_data['v_lead'], x, y) + # TR_mod += interp(self.get_acceleration(), x, y) # todo: when lead car has been braking over the past 3 seconds, slightly increase TR TR += TR_mod #TR *= self.get_traffic_level() # modify TR based on last minute of traffic data # todo: look at getting this to work, a model could be used @@ -138,8 +139,8 @@ def smooth_follow(self): # in m/s def get_cost(self, TR): x = [.9, 1.8, 2.7] y = [4.5, 2.8, 1.3] - if self.x_lead is not None and self.v_ego is not None and self.v_ego != 0: - real_TR = self.x_lead / float(self.v_ego) # switched to cost generation using actual distance from lead car; should be safer + if self.lead_data['x_lead'] is not None and self.v_ego is not None and self.v_ego != 0: + real_TR = self.lead_data['x_lead'] / float(self.v_ego) # switched to cost generation using actual distance from lead car; should be safer if abs(real_TR - TR) >= .25: # use real TR if diff is greater than x safety threshold TR = real_TR if self.v_lead is not None and self.v_ego > 5: @@ -176,19 +177,6 @@ def get_TR(self): self.last_cost = 0.05 return 2.7 # 30m at 40km/hr - def calc_rate(self, seconds=1.0, new_frame=False): # return current rate of long_mpc in fps/hertz - current_time = time.time() - if self.last_time is None or (current_time - self.last_time) <= 0: - rate = int(round(40.42 * seconds)) # average of tests on long_mpc - else: - rate = (1.0 / (current_time - self.last_time)) * seconds - - min_return = 10 - max_return = seconds * 100 - if new_frame: - self.last_time = current_time - return int(round(max(min(rate, max_return), min_return))) # ensure we return a value between range, in hertz - def process_phantom(self, lead): if lead is not None and lead.status: v_lead = max(0.0, lead.vLead) @@ -233,7 +221,7 @@ def update(self, pm, CS, lead, v_cruise_setpoint): self.prev_lead_x = x_lead self.cur_state[0].x_l = x_lead self.cur_state[0].v_l = v_lead - elif lead is not None and lead.status: + elif lead is not None and lead.status: # not phantom, is lead x_lead = lead.dRel v_lead = max(0.0, lead.vLead) a_lead = lead.aLeadK @@ -242,8 +230,7 @@ def update(self, pm, CS, lead, v_cruise_setpoint): v_lead = 0.0 a_lead = 0.0 - self.v_lead = v_lead - self.x_lead = x_lead + self.lead_data['v_lead'], self.lead_data['x_lead'], self.lead_data['a_lead'] = v_lead, x_lead, a_lead self.a_lead_tau = lead.aLeadTau self.new_lead = False @@ -255,14 +242,13 @@ def update(self, pm, CS, lead, v_cruise_setpoint): self.prev_lead_x = x_lead self.cur_state[0].x_l = x_lead self.cur_state[0].v_l = v_lead - else: + else: # no lead self.prev_lead_status = False # Fake a fast lead car, so mpc keeps running self.cur_state[0].x_l = 50.0 self.cur_state[0].v_l = v_ego + 10.0 a_lead = 0.0 - self.v_lead = None - self.x_lead = None + self.lead_data['v_lead'], self.lead_data['x_lead'], self.lead_data['a_lead'] = (None,) * 3 self.a_lead_tau = _LEAD_ACCEL_TAU # Calculate mpc From 046db479d6b0a55be5a3ea73a450c088313691a6 Mon Sep 17 00:00:00 2001 From: Shane Date: Mon, 18 Nov 2019 14:57:08 -0600 Subject: [PATCH 19/34] update to messagine_arne.submaster in controlsd, updates for longcontrol --- selfdrive/controls/controlsd.py | 33 +++++++----------- selfdrive/controls/lib/long_mpc.py | 2 +- selfdrive/controls/lib/longcontrol.py | 49 +++++++++++++++------------ 3 files changed, 40 insertions(+), 44 deletions(-) diff --git a/selfdrive/controls/controlsd.py b/selfdrive/controls/controlsd.py index 6cc91ff15ba54a..76d43e0b715cc2 100644 --- a/selfdrive/controls/controlsd.py +++ b/selfdrive/controls/controlsd.py @@ -219,7 +219,7 @@ def state_transition(frame, CS, CP, state, events, soft_disable_timer, v_cruise_ def state_control(frame, rcv_frame, plan, path_plan, CS, CP, state, events, v_cruise_kph, v_cruise_kph_last, - AM, rk, driver_status, LaC, LoC, read_only, is_metric, cal_perc, sm, poller, arne182Status): + AM, rk, driver_status, LaC, LoC, read_only, is_metric, cal_perc, radar_state, arne_sm): """Given the state, this function returns an actuators packet""" actuators = car.CarControl.Actuators.new_message() @@ -262,27 +262,16 @@ def state_control(frame, rcv_frame, plan, path_plan, CS, CP, state, events, v_cr a_acc_sol = plan.aStart + (dt / LON_MPC_STEP) * (plan.aTarget - plan.aStart) v_acc_sol = plan.vStart + dt * (a_acc_sol + plan.aStart) / 2.0 - try: - gasinterceptor = CP.enableGasInterceptor - except AttributeError: - gasinterceptor = False + # Gas/Brake PID loop - try: - leadOne = sm['radarState'].leadOne - except KeyError: - leadOne = None - gasstatus = None - for socket, _ in poller.poll(0): - if socket is arne182Status: - gasstatus = arne182.Arne182Status.from_bytes(socket.recv()) - if gasstatus is None: - gasbuttonstatus = 0 - else: - gasbuttonstatus = gasstatus.gasbuttonstatus - actuators.gas, actuators.brake = LoC.update(active, CS.vEgo, CS.brakePressed, CS.standstill, CS.cruiseState.standstill, - v_cruise_kph, v_acc_sol, plan.vTargetFuture, a_acc_sol, CP, gasinterceptor, gasbuttonstatus, plan.decelForTurn, plan.longitudinalPlanSource, - leadOne, CS.gasPressed, plan.fcw) + arne_sm.update(0) + gas_button_status = arne_sm['arne182Status'].gasbuttonstatus + actuators.gas, actuators.brake = LoC.update(active, CS.vEgo, CS.brakePressed, CS.standstill, + CS.cruiseState.standstill, + v_cruise_kph, v_acc_sol, plan.vTargetFuture, a_acc_sol, CP, + gas_button_status, plan.decelForTurn, plan.longitudinalPlanSource, + radar_state.leadOne, CS.gasPressed, plan.fcw) # Steering PID loop and lateral MPC actuators.steer, actuators.steerAngle, lac_log = LaC.update(active, CS.vEgo, CS.steeringAngle, CS.steeringRate, CS.steeringTorqueEps, CS.steeringPressed, CP, path_plan) @@ -459,6 +448,8 @@ def controlsd_thread(sm=None, pm=None, can_sock=None): sm = messaging.SubMaster(['thermal', 'health', 'liveCalibration', 'driverMonitoring', 'plan', 'pathPlan', \ 'gpsLocation', 'radarState'], ignore_alive=['gpsLocation']) + arne_sm = messaging_arne.SubMaster(['arne182Status']) + arne182Status = messaging_arne.sub_sock('arne182Status', conflate=True) if can_sock is None: can_timeout = None if os.environ.get('NO_CAN_TIMEOUT', False) else 100 @@ -574,7 +565,7 @@ def controlsd_thread(sm=None, pm=None, can_sock=None): # Compute actuators (runs PID loops and lateral MPC) actuators, v_cruise_kph, driver_status, v_acc, a_acc, lac_log = \ state_control(sm.frame, sm.rcv_frame, sm['plan'], sm['pathPlan'], CS, CP, state, events, v_cruise_kph, v_cruise_kph_last, AM, rk, - driver_status, LaC, LoC, read_only, is_metric, cal_perc, sm, poller, arne182Status) + driver_status, LaC, LoC, read_only, is_metric, cal_perc, sm['radarState'], arne_sm) prof.checkpoint("State Control") diff --git a/selfdrive/controls/lib/long_mpc.py b/selfdrive/controls/lib/long_mpc.py index cd9e0155f1377e..803d6da1f78528 100644 --- a/selfdrive/controls/lib/long_mpc.py +++ b/selfdrive/controls/lib/long_mpc.py @@ -32,7 +32,7 @@ def __init__(self, mpc_id): self.car_data = {"lead_vels": [], "traffic_vels": []} self.mpc_frame = 0 # idea thanks to kegman self.last_time = None - self.lead_data = {'v_lead': None, 'x_lead': None, 'a_lead': None, 'status': False} + self.lead_data = {'v_lead': None, 'x_lead': None, 'a_lead': None} self.df_frame = 0 self.rate = 20 self.phantom = Phantom(timeout=1.) diff --git a/selfdrive/controls/lib/longcontrol.py b/selfdrive/controls/lib/longcontrol.py index 76854a6a8ff14d..b5bca853531f17 100644 --- a/selfdrive/controls/lib/longcontrol.py +++ b/selfdrive/controls/lib/longcontrol.py @@ -1,6 +1,7 @@ from cereal import log from common.numpy_fast import clip, interp from selfdrive.controls.lib.pid import PIController +import time LongCtrlState = log.ControlsState.LongControlState @@ -68,9 +69,9 @@ def __init__(self, CP, compute_gb): self.fcw_countdown = 0 self.last_output_gb = 0.0 self.lastdecelForTurn = False - self.last_lead = None + self.last_lead_data = {'vRel': None, 'a_lead': None, 'x_lead': None, 'status': False} self.freeze = False - self.none_count = 0 + self.last_lead_time = time.time() def reset(self, v_pid): """Reset PID controller and change setpoint""" @@ -103,40 +104,44 @@ def dynamic_gas(self, v_ego, gas_interceptor, gas_button_status): accel = interp(v_ego, x, y) - if self.none_count < 10 and self.last_lead is not None and self.last_lead.status: # if returned nones is less than 10, last lead is not none, and last lead's status is true assume lead - v_rel = self.last_lead.vRel - #a_lead = self.last_lead.aLeadK # to use later - #x_lead = self.last_lead.dRel - else: - v_rel = None - #a_lead = None - #x_lead = None - - if dynamic and v_rel is not None: # dynamic gas profile specific operations, and if lead + if dynamic and self.last_lead_data['vRel'] is not None and self.last_lead_data['status']: # dynamic gas profile specific operations, and if lead if v_ego < 6.7056: # if under 15 mph x = [1.61479, 1.99067, 2.28537, 2.49888, 2.6312, 2.68224] y = [-accel, -(accel / 1.06), -(accel / 1.2), -(accel / 1.8), -(accel / 4.4), 0] # array that matches current chosen accel value - accel += interp(v_rel, x, y) + accel += interp(self.last_lead_data['vRel'], x, y) else: x = [-0.89408, 0, 0.89408, 4.4704] y = [-.15, -.05, .005, .05] - accel += interp(v_rel, x, y) + accel += interp(self.last_lead_data['vRel'], x, y) min_return = 0.0 max_return = 1.0 return round(max(min(accel, max_return), min_return), 5) # ensure we return a value between range - def update(self, active, v_ego, brake_pressed, standstill, cruise_standstill, v_cruise, v_target, v_target_future, a_target, CP, gas_interceptor, + def process_lead(self, lead_one): + if lead_one is not None: + self.last_lead_data['vRel'] = lead_one.vRel + self.last_lead_data['a_lead'] = lead_one.aLeadK + self.last_lead_data['x_lead'] = lead_one.dRel + self.last_lead_data['status'] = lead_one.status + self.last_lead_time = time.time() + elif time.time() - self.last_lead_time > 0.5: # if missing lead for n seconds + self.last_lead_data['vRel'] = None + self.last_lead_data['a_lead'] = None + self.last_lead_data['x_lead'] = None + self.last_lead_data['status'] = False + + def update(self, active, v_ego, brake_pressed, standstill, cruise_standstill, v_cruise, v_target, v_target_future, a_target, CP, gas_button_status, decelForTurn, longitudinalPlanSource, lead_one, gas_pressed, fcw): """Update longitudinal control. This updates the state machine and runs a PID loop""" # Actuation limits - if lead_one is not None: - self.last_lead = lead_one - self.none_count = 0 - else: - self.none_count = clip(self.none_count + 1, 0, 10) + self.process_lead(lead_one) + try: + gas_interceptor = CP.enableGasInterceptor + except AttributeError: + gas_interceptor = False - #gas_max = interp(v_ego, CP.gasMaxBP, CP.gasMaxV) + # gas_max = interp(v_ego, CP.gasMaxBP, CP.gasMaxV) gas_max = self.dynamic_gas(v_ego, gas_interceptor, gas_button_status) brake_max = interp(v_ego, CP.brakeMaxBP, CP.brakeMaxV) @@ -157,7 +162,7 @@ def update(self, active, v_ego, brake_pressed, standstill, cruise_standstill, v_ elif self.long_control_state == LongCtrlState.pid: self.v_pid = v_target self.pid.pos_limit = gas_max - self.pid.neg_limit = - brake_max + self.pid.neg_limit = -brake_max # Toyota starts braking more when it thinks you want to stop # Freeze the integrator so we don't accelerate to compensate, and don't allow positive acceleration From c8043173555587736404896c0b1ac8c8ca061aad Mon Sep 17 00:00:00 2001 From: Shane Date: Mon, 18 Nov 2019 15:04:57 -0600 Subject: [PATCH 20/34] update pathplanner to use messaging_arne and pubmaster! --- selfdrive/controls/lib/pathplanner.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/selfdrive/controls/lib/pathplanner.py b/selfdrive/controls/lib/pathplanner.py index 53b04c522c04aa..6cf16591a039e3 100644 --- a/selfdrive/controls/lib/pathplanner.py +++ b/selfdrive/controls/lib/pathplanner.py @@ -1,5 +1,4 @@ import math -from cereal import arne182 from common.realtime import sec_since_boot from selfdrive.swaglog import cloudlog from selfdrive.controls.lib.lateral_mpc import libmpc_py @@ -24,7 +23,7 @@ def __init__(self, CP): self.last_cloudlog_t = 0 if not travis: - self.latControl_sock = messaging_arne.pub_sock('latControl') + self.arne_pm = messaging_arne.PubMaster('latControl') self.setup_mpc(CP.steerRateCost) self.solution_invalid_cnt = 0 self.path_offset_i = 0.0 @@ -140,8 +139,9 @@ def update(self, sm, pm, CP, VM): dat.liveMpc.delta = list(self.mpc_solution[0].delta) dat.liveMpc.cost = self.mpc_solution[0].cost pm.send('liveMpc', dat) - - msg = arne182.LatControl.new_message() + + msg = messaging_arne.new_message() + msg.init('latControl') msg.anglelater = math.degrees(list(self.mpc_solution[0].delta)[-1]) if not travis: - self.latControl_sock.send(msg.to_bytes()) + self.arne_pm.send('latControl', msg) From ceb5ef645deb66885d041d2ddfdff6b27482ade9 Mon Sep 17 00:00:00 2001 From: Shane Date: Mon, 18 Nov 2019 15:13:15 -0600 Subject: [PATCH 21/34] - allow pubmaster and submaster to be initialized with 1 service as a str, convert to list - update carstate to messaging_arne and pubmaster --- selfdrive/car/toyota/carstate.py | 15 ++++++++------- selfdrive/controls/controlsd.py | 2 +- selfdrive/messaging_arne/__init__.py | 4 ++++ 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/selfdrive/car/toyota/carstate.py b/selfdrive/car/toyota/carstate.py index 55f70d813e88c4..08c85b61674fe8 100644 --- a/selfdrive/car/toyota/carstate.py +++ b/selfdrive/car/toyota/carstate.py @@ -1,7 +1,7 @@ import numpy as np import math -from cereal import arne182 import selfdrive.messaging as messaging +import selfdrive.messaging_arne as messaging_arne from common.numpy_fast import interp from cereal import car from common.numpy_fast import mean @@ -140,8 +140,7 @@ def __init__(self, CP): self.Angle = [0, 5, 10, 15,20,25,30,35,60,100,180,270,500] self.Angle_Speed = [255,160,100,80,70,60,55,50,40,33,27,17,12] if not travis: - self.traffic_data_sock = messaging.pub_sock('liveTrafficData') - self.arne182Status_sock = messaging.pub_sock('arne182Status') + self.arne_pm = messaging_arne.PubMaster(['liveTrafficData', 'arne182Status']) # initialize can parser self.car_fingerprint = CP.carFingerprint @@ -217,11 +216,12 @@ def update(self, cp, cp_cam): self.gasbuttonstatus = 2 if self.sport_on == 0 and self.econ_on == 0: self.gasbuttonstatus = 0 - msg = arne182.Arne182Status.new_message() + msg = messaging_arne.new_message() + msg.init('arne182Status') msg.gasbuttonstatus = self.gasbuttonstatus msg.readdistancelines = cp.vl["PCM_CRUISE_SM"]['DISTANCE_LINES'] if not travis: - self.arne182Status_sock.send(msg.to_bytes()) + self.arne_pm.send('arne182Status', msg) if self.CP.carFingerprint == CAR.LEXUS_IS: self.main_on = cp.vl["DSU_CRUISE"]['MAIN_ON'] else: @@ -312,7 +312,8 @@ def update(self, cp, cp_cam): self.splsgn4 = cp_cam.vl["RSA2"]['SPLSGN4'] self.noovertake = self.tsgn1 == 65 or self.tsgn2 == 65 or self.tsgn3 == 65 or self.tsgn4 == 65 or self.tsgn1 == 66 or self.tsgn2 == 66 or self.tsgn3 == 66 or self.tsgn4 == 66 if self.spdval1 > 0 or self.spdval2 > 0: - dat = arne182.LiveTrafficData.new_message() + dat = messaging_arne.new_message() + dat.init('liveTrafficData') if self.spdval1 > 0: dat.speedLimitValid = True if self.tsgn1 == 36: @@ -329,4 +330,4 @@ def update(self, cp, cp_cam): else: dat.speedAdvisoryValid = False if not travis: - self.traffic_data_sock.send(dat.to_bytes()) + self.arne_pm.send('liveTrafficData', dat) diff --git a/selfdrive/controls/controlsd.py b/selfdrive/controls/controlsd.py index 76d43e0b715cc2..3bf96609be2dfb 100644 --- a/selfdrive/controls/controlsd.py +++ b/selfdrive/controls/controlsd.py @@ -448,7 +448,7 @@ def controlsd_thread(sm=None, pm=None, can_sock=None): sm = messaging.SubMaster(['thermal', 'health', 'liveCalibration', 'driverMonitoring', 'plan', 'pathPlan', \ 'gpsLocation', 'radarState'], ignore_alive=['gpsLocation']) - arne_sm = messaging_arne.SubMaster(['arne182Status']) + arne_sm = messaging_arne.SubMaster('arne182Status') arne182Status = messaging_arne.sub_sock('arne182Status', conflate=True) if can_sock is None: diff --git a/selfdrive/messaging_arne/__init__.py b/selfdrive/messaging_arne/__init__.py index 05eaeec3a5c537..9811bdbba0ba8d 100644 --- a/selfdrive/messaging_arne/__init__.py +++ b/selfdrive/messaging_arne/__init__.py @@ -119,6 +119,8 @@ def get_one_can(logcan): class SubMaster(): def __init__(self, services, ignore_alive=None, addr="127.0.0.1"): self.poller = Poller() + if isinstance(services, str): + services = [services] self.frame = -1 self.updated = {s : False for s in services} self.rcv_time = {s : 0. for s in services} @@ -204,6 +206,8 @@ def all_alive_and_valid(self, service_list=None): class PubMaster(): def __init__(self, services): self.sock = {} + if isinstance(services, str): + services = [services] for s in services: self.sock[s] = pub_sock(s) From 7cdbf1300e2b25a8d40adfeea64ab927b1b8956a Mon Sep 17 00:00:00 2001 From: Shane Date: Mon, 18 Nov 2019 15:16:30 -0600 Subject: [PATCH 22/34] update planner to use submaster --- selfdrive/controls/lib/planner.py | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/selfdrive/controls/lib/planner.py b/selfdrive/controls/lib/planner.py index 800f94cecd3797..7d9bf1fc72ee74 100644 --- a/selfdrive/controls/lib/planner.py +++ b/selfdrive/controls/lib/planner.py @@ -4,7 +4,6 @@ import time import zmq import numpy as np -from cereal import arne182 from common.params import Params from common.numpy_fast import interp import selfdrive.messaging_arne as messaging_arne @@ -97,9 +96,11 @@ def limit_accel_in_turns(v_ego, angle_steers, a_target, CP, angle_later): class Planner(): def __init__(self, CP): self.CP = CP - self.poller = zmq.Poller() - self.arne182Status = messaging_arne.sub_sock('arne182Status', conflate=True) - self.latcontolStatus = messaging_arne.sub_sock('latControl', conflate=True) + self.arne_sm = messaging_arne.SubMaster(['arne182Status', 'latControl']) + self.arne182 = None + self.latcontrol = None + # self.arne182Status = messaging_arne.sub_sock('arne182Status', conflate=True) + # self.latcontolStatus = messaging_arne.sub_sock('latControl', conflate=True) self.mpc1 = LongitudinalMpc(1) self.mpc2 = LongitudinalMpc(2) @@ -150,11 +151,9 @@ def choose_solution(self, v_cruise_setpoint, enabled): def update(self, sm, pm, CP, VM, PP): self.arne182 = None self.latcontrol = None - for socket, _ in self.poller.poll(0): - if socket is self.arne182Status: - self.arne182 = arne182.Arne182Status.from_bytes(socket.recv()) - elif socket is self.latcontolStatus: - self.latcontrol = arne182.LatControl.from_bytes(socket.recv()) + self.arne_sm.update(0) + self.arne182 = self.arne_sm['arne182Status'] + self.latcontrol = self.arne_sm['latControl'] if self.arne182 is None: gasbuttonstatus = 0 else: From a187ec802e8bf205bc42a0ab13cae790bff31c52 Mon Sep 17 00:00:00 2001 From: Shane Date: Mon, 18 Nov 2019 15:20:10 -0600 Subject: [PATCH 23/34] some clean up --- selfdrive/controls/controlsd.py | 3 +-- selfdrive/controls/lib/planner.py | 26 +++++++++++++------------- 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/selfdrive/controls/controlsd.py b/selfdrive/controls/controlsd.py index 3bf96609be2dfb..cf0b52bf27c949 100644 --- a/selfdrive/controls/controlsd.py +++ b/selfdrive/controls/controlsd.py @@ -4,7 +4,7 @@ import capnp import zmq import selfdrive.messaging_arne as messaging_arne -from cereal import car, log, arne182 +from cereal import car, log from common.numpy_fast import clip from common.realtime import sec_since_boot, set_realtime_priority, Ratekeeper, DT_CTRL from common.profiler import Profiler @@ -450,7 +450,6 @@ def controlsd_thread(sm=None, pm=None, can_sock=None): arne_sm = messaging_arne.SubMaster('arne182Status') - arne182Status = messaging_arne.sub_sock('arne182Status', conflate=True) if can_sock is None: can_timeout = None if os.environ.get('NO_CAN_TIMEOUT', False) else 100 can_sock = messaging.sub_sock('can', timeout=can_timeout) diff --git a/selfdrive/controls/lib/planner.py b/selfdrive/controls/lib/planner.py index 7d9bf1fc72ee74..3f8ae59643036f 100644 --- a/selfdrive/controls/lib/planner.py +++ b/selfdrive/controls/lib/planner.py @@ -58,7 +58,7 @@ # 75th percentile SPEED_PERCENTILE_IDX = 7 -def calc_cruise_accel_limits(v_ego, following, gasbuttonstatus): +def calc_cruise_accel_limits(v_ego, following, gas_button_status): if following: a_cruise_min = interp(v_ego, _A_CRUISE_MIN_BP, _A_CRUISE_MIN_V_FOLLOWING) else: @@ -67,9 +67,9 @@ def calc_cruise_accel_limits(v_ego, following, gasbuttonstatus): if following: a_cruise_max = interp(v_ego, _A_CRUISE_MAX_BP, _A_CRUISE_MAX_V_FOLLOWING) else: - if gasbuttonstatus == 1: + if gas_button_status == 1: a_cruise_max = interp(v_ego, _A_CRUISE_MAX_BP, _A_CRUISE_MAX_V_SPORT) - elif gasbuttonstatus == 2: + elif gas_button_status == 2: a_cruise_max = interp(v_ego, _A_CRUISE_MAX_BP, _A_CRUISE_MAX_V_ECO) else: a_cruise_max = interp(v_ego, _A_CRUISE_MAX_BP, _A_CRUISE_MAX_V) @@ -98,7 +98,7 @@ def __init__(self, CP): self.CP = CP self.arne_sm = messaging_arne.SubMaster(['arne182Status', 'latControl']) self.arne182 = None - self.latcontrol = None + self.lat_control = None # self.arne182Status = messaging_arne.sub_sock('arne182Status', conflate=True) # self.latcontolStatus = messaging_arne.sub_sock('latControl', conflate=True) self.mpc1 = LongitudinalMpc(1) @@ -150,14 +150,14 @@ def choose_solution(self, v_cruise_setpoint, enabled): def update(self, sm, pm, CP, VM, PP): self.arne182 = None - self.latcontrol = None + self.lat_control = None self.arne_sm.update(0) self.arne182 = self.arne_sm['arne182Status'] - self.latcontrol = self.arne_sm['latControl'] + self.lat_control = self.arne_sm['latControl'] if self.arne182 is None: - gasbuttonstatus = 0 + gas_button_status = 0 else: - gasbuttonstatus = self.arne182.gasbuttonstatus + gas_button_status = self.arne182.gasbuttonstatus """Gets called when new radarState is available""" cur_time = sec_since_boot() v_ego = sm['carState'].vEgo @@ -167,14 +167,14 @@ def update(self, sm, pm, CP, VM, PP): angle_later = 0. else: steering_angle = sm['carState'].steeringAngle - if self.latcontrol is None or v_ego < 11: + if self.lat_control is None or v_ego < 11: angle_later = 0. else: - angle_later = self.latcontrol.anglelater + angle_later = self.lat_control.anglelater - if gasbuttonstatus == 1: + if gas_button_status == 1: speed_ahead_distance = 150 - elif gasbuttonstatus == 2: + elif gas_button_status == 2: speed_ahead_distance = 350 else: speed_ahead_distance = 250 @@ -260,7 +260,7 @@ def update(self, sm, pm, CP, VM, PP): # Calculate speed for normal cruise control if enabled: - accel_limits = [float(x) for x in calc_cruise_accel_limits(v_ego, following, gasbuttonstatus)] + accel_limits = [float(x) for x in calc_cruise_accel_limits(v_ego, following, gas_button_status)] jerk_limits = [min(-0.1, accel_limits[0]), max(0.1, accel_limits[1])] # TODO: make a separate lookup for jerk tuning accel_limits_turns = limit_accel_in_turns(v_ego, steering_angle, accel_limits, self.CP, angle_later) From 0bf6d4a3f5f6f9bbd590e8d21510921572197f79 Mon Sep 17 00:00:00 2001 From: Shane Date: Mon, 18 Nov 2019 15:28:46 -0600 Subject: [PATCH 24/34] testing submaster --- selfdrive/phantom.py | 36 ++++++++++++++++++++--------------- selfdrive/phantom_receiver.py | 11 ++++++----- 2 files changed, 27 insertions(+), 20 deletions(-) diff --git a/selfdrive/phantom.py b/selfdrive/phantom.py index eed89c399301b2..94bdd729079ae1 100644 --- a/selfdrive/phantom.py +++ b/selfdrive/phantom.py @@ -10,7 +10,8 @@ class Phantom: def __init__(self, timeout=1.): context = zmq.Context() self.op_params = opParams() - self.phantom_Data_sock = messaging_arne.sub_sock('phantomData', conflate=True) + self.sm = messaging_arne.SubMaster('phantomData') + # self.phantom_Data_sock = messaging_arne.sub_sock('phantomData', conflate=True) self.data = {"status": False, "speed": 0.0} self.last_receive_time = time.time() self.last_phantom_data = {"status": False, "speed": 0.0} @@ -20,20 +21,25 @@ def __init__(self, timeout=1.): self.mod_sshd_config() def update(self): - phantom_data = messaging_arne.recv_one_or_none(self.phantom_Data_sock) - if phantom_data is not None: - self.data = {"status": phantom_data.phantomData.status, "speed": phantom_data.phantomData.speed, - "angle": phantom_data.phantomData.angle, "time": phantom_data.phantomData.time} - self.last_phantom_data = dict(self.data) - self.last_receive_time = time.time() - self.to_disable = not self.data["status"] - else: - if self.to_disable: # if last message is status: False, disable phantom mode, also disable by default - self.data = {"status": False, "speed": 0.0} - elif time.time() - self.last_receive_time >= self.timeout: # lost connection, don't disable. keep phantom on but set speed to 0 - self.data = {"status": True, "speed": 0.0, "angle": 0.0, "time": 0.0, "lost_connection": True} - else: # if waiting between messages from app, message becomes none, this uses the data from last message - self.data = dict(self.last_phantom_data) + self.sm.update(0) + phantom_data = self.sm['phantomData'] + updated = self.sm.updated['phantomData'] + print('Updated: {}'.format(updated)) + print([phantom_data.status, phantom_data.speed, phantom_data.angle, phantom_data.time]) + # phantom_data = messaging_arne.recv_one_or_none(self.phantom_Data_sock) + # if phantom_data is not None: + # self.data = {"status": phantom_data.phantomData.status, "speed": phantom_data.phantomData.speed, + # "angle": phantom_data.phantomData.angle, "time": phantom_data.phantomData.time} + # self.last_phantom_data = dict(self.data) + # self.last_receive_time = time.time() + # self.to_disable = not self.data["status"] + # else: + # if self.to_disable: # if last message is status: False, disable phantom mode, also disable by default + # self.data = {"status": False, "speed": 0.0} + # elif time.time() - self.last_receive_time >= self.timeout: # lost connection, don't disable. keep phantom on but set speed to 0 + # self.data = {"status": True, "speed": 0.0, "angle": 0.0, "time": 0.0, "lost_connection": True} + # else: # if waiting between messages from app, message becomes none, this uses the data from last message + # self.data = dict(self.last_phantom_data) def mod_sshd_config(self): # this disables dns lookup when connecting to EON to speed up commands from phantom app, reboot required diff --git a/selfdrive/phantom_receiver.py b/selfdrive/phantom_receiver.py index 09cffc988f238b..53a2db23478b94 100644 --- a/selfdrive/phantom_receiver.py +++ b/selfdrive/phantom_receiver.py @@ -3,24 +3,25 @@ class PhantomReceiver: def __init__(self): - self.phantom_data_sock = None + # self.phantom_data_sock = None + self.pm = None def receive_data(self, speed, angle, time): self.broadcast_data(True, speed, angle, time) def broadcast_data(self, status, speed, angle, time): - with open('/data/bd.test', 'a') as f: - f.write('{}\n'.format([status, speed, angle, time])) phantom_data = messaging_arne.new_message() phantom_data.init('phantomData') phantom_data.phantomData.status = status phantom_data.phantomData.speed = speed phantom_data.phantomData.angle = angle phantom_data.phantomData.time = time - self.phantom_data_sock.send(phantom_data.to_bytes()) + self.pm.send('phantomData', phantom_data) + # self.phantom_data_sock.send(phantom_data.to_bytes()) def enable_phantom(self): - self.phantom_data_sock = messaging_arne.pub_sock('phantomData') + self.pm = messaging_arne.SubMaster('phantomData') + # self.phantom_data_sock = messaging_arne.pub_sock('phantomData') return "ENABLED" # needed to tell the app we're all done with this function def disable_phantom(self): From 277ba00dfadc6a723622924fd512b124ab2c0a5f Mon Sep 17 00:00:00 2001 From: Shane Date: Mon, 18 Nov 2019 15:30:51 -0600 Subject: [PATCH 25/34] whoops --- selfdrive/phantom_receiver.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/selfdrive/phantom_receiver.py b/selfdrive/phantom_receiver.py index 53a2db23478b94..43b913c5f65b09 100644 --- a/selfdrive/phantom_receiver.py +++ b/selfdrive/phantom_receiver.py @@ -20,7 +20,7 @@ def broadcast_data(self, status, speed, angle, time): # self.phantom_data_sock.send(phantom_data.to_bytes()) def enable_phantom(self): - self.pm = messaging_arne.SubMaster('phantomData') + self.pm = messaging_arne.PubMaster('phantomData') # self.phantom_data_sock = messaging_arne.pub_sock('phantomData') return "ENABLED" # needed to tell the app we're all done with this function From ce6840d5df31506d035e68cae9a4f7b2f96d29f0 Mon Sep 17 00:00:00 2001 From: Shane Date: Mon, 18 Nov 2019 15:36:20 -0600 Subject: [PATCH 26/34] testing conflate --- selfdrive/messaging_arne/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/selfdrive/messaging_arne/__init__.py b/selfdrive/messaging_arne/__init__.py index 9811bdbba0ba8d..4d0ab775713a45 100644 --- a/selfdrive/messaging_arne/__init__.py +++ b/selfdrive/messaging_arne/__init__.py @@ -140,7 +140,7 @@ def __init__(self, services, ignore_alive=None, addr="127.0.0.1"): for s in services: # TODO: get address automatically from service_list if addr is not None: - self.sock[s] = sub_sock(s, poller=self.poller, addr=addr, conflate=True) + self.sock[s] = sub_sock(s, poller=self.poller, addr=addr, conflate=False) self.freq[s] = service_list[s].frequency data = new_message() From 2a0753e76bfadb5cf915e262a234a35926c9456e Mon Sep 17 00:00:00 2001 From: Shane Date: Mon, 18 Nov 2019 15:56:44 -0600 Subject: [PATCH 27/34] updates to phantom --- selfdrive/car/toyota/carcontroller.py | 2 +- selfdrive/controls/lib/long_mpc.py | 3 +- selfdrive/messaging_arne/__init__.py | 15 ++++++++-- selfdrive/phantom/__init__.py | 0 selfdrive/{ => phantom}/phantom.py | 31 +++++++-------------- selfdrive/{ => phantom}/phantom_receiver.py | 12 ++------ 6 files changed, 27 insertions(+), 36 deletions(-) create mode 100644 selfdrive/phantom/__init__.py rename selfdrive/{ => phantom}/phantom.py (52%) rename selfdrive/{ => phantom}/phantom_receiver.py (66%) diff --git a/selfdrive/car/toyota/carcontroller.py b/selfdrive/car/toyota/carcontroller.py index 4ad3c097632dd3..3548fb9e39d62a 100644 --- a/selfdrive/car/toyota/carcontroller.py +++ b/selfdrive/car/toyota/carcontroller.py @@ -8,7 +8,7 @@ create_acc_cancel_command, create_fcw_command from selfdrive.car.toyota.values import CAR, ECU, STATIC_MSGS, TSS2_CAR, SteerLimitParams from selfdrive.can.packer import CANPacker -from selfdrive.phantom import Phantom +from selfdrive.phantom.phantom import Phantom VisualAlert = car.CarControl.HUDControl.VisualAlert diff --git a/selfdrive/controls/lib/long_mpc.py b/selfdrive/controls/lib/long_mpc.py index 803d6da1f78528..77749f80fa7717 100644 --- a/selfdrive/controls/lib/long_mpc.py +++ b/selfdrive/controls/lib/long_mpc.py @@ -8,8 +8,7 @@ from selfdrive.controls.lib.radar_helpers import _LEAD_ACCEL_TAU from selfdrive.controls.lib.longitudinal_mpc import libmpc_py from selfdrive.controls.lib.drive_helpers import MPC_COST_LONG -from selfdrive.phantom import Phantom -import time +from selfdrive.phantom.phantom import Phantom LOG_MPC = os.environ.get('LOG_MPC', False) diff --git a/selfdrive/messaging_arne/__init__.py b/selfdrive/messaging_arne/__init__.py index 4d0ab775713a45..0b6ead0e70b513 100644 --- a/selfdrive/messaging_arne/__init__.py +++ b/selfdrive/messaging_arne/__init__.py @@ -117,7 +117,18 @@ def get_one_can(logcan): return can class SubMaster(): - def __init__(self, services, ignore_alive=None, addr="127.0.0.1"): + def __init__(self, services, ignore_alive=None, addr="127.0.0.1", conflate=True): + ''' + :param services: + :param ignore_alive: + :param addr: + :param conflate: if set to true, SubMaster will return only the last available message. If you send two messages + before SubMaster has a chance to update, it will only return the last message. However, if set + to false, SubMaster would return the first message on the first update call, and the second message + on the second update. This could this cause SubMaster to get behind if we're sending at a higher rate + than receiving/updating + ''' + self.poller = Poller() if isinstance(services, str): services = [services] @@ -140,7 +151,7 @@ def __init__(self, services, ignore_alive=None, addr="127.0.0.1"): for s in services: # TODO: get address automatically from service_list if addr is not None: - self.sock[s] = sub_sock(s, poller=self.poller, addr=addr, conflate=False) + self.sock[s] = sub_sock(s, poller=self.poller, addr=addr, conflate=conflate) self.freq[s] = service_list[s].frequency data = new_message() diff --git a/selfdrive/phantom/__init__.py b/selfdrive/phantom/__init__.py new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/selfdrive/phantom.py b/selfdrive/phantom/phantom.py similarity index 52% rename from selfdrive/phantom.py rename to selfdrive/phantom/phantom.py index 94bdd729079ae1..2150894febd709 100644 --- a/selfdrive/phantom.py +++ b/selfdrive/phantom/phantom.py @@ -8,38 +8,27 @@ class Phantom: def __init__(self, timeout=1.): - context = zmq.Context() self.op_params = opParams() self.sm = messaging_arne.SubMaster('phantomData') - # self.phantom_Data_sock = messaging_arne.sub_sock('phantomData', conflate=True) self.data = {"status": False, "speed": 0.0} self.last_receive_time = time.time() - self.last_phantom_data = {"status": False, "speed": 0.0} self.timeout = timeout # in seconds - self.to_disable = True if not travis and not self.op_params.get("UseDNS", None): # ensure we only run once self.mod_sshd_config() def update(self): self.sm.update(0) phantom_data = self.sm['phantomData'] - updated = self.sm.updated['phantomData'] - print('Updated: {}'.format(updated)) - print([phantom_data.status, phantom_data.speed, phantom_data.angle, phantom_data.time]) - # phantom_data = messaging_arne.recv_one_or_none(self.phantom_Data_sock) - # if phantom_data is not None: - # self.data = {"status": phantom_data.phantomData.status, "speed": phantom_data.phantomData.speed, - # "angle": phantom_data.phantomData.angle, "time": phantom_data.phantomData.time} - # self.last_phantom_data = dict(self.data) - # self.last_receive_time = time.time() - # self.to_disable = not self.data["status"] - # else: - # if self.to_disable: # if last message is status: False, disable phantom mode, also disable by default - # self.data = {"status": False, "speed": 0.0} - # elif time.time() - self.last_receive_time >= self.timeout: # lost connection, don't disable. keep phantom on but set speed to 0 - # self.data = {"status": True, "speed": 0.0, "angle": 0.0, "time": 0.0, "lost_connection": True} - # else: # if waiting between messages from app, message becomes none, this uses the data from last message - # self.data = dict(self.last_phantom_data) + self.data = {"status": phantom_data.status, "speed": phantom_data.speed, + "angle": phantom_data.angle, "time": phantom_data.time} + + if self.sm.updated['phantomData']: + self.last_receive_time = time.time() + + if time.time() - self.last_receive_time >= self.timeout and self.data['status']: + self.data = {"status": True, "speed": 0.0, "angle": 0.0, "time": 0.0, "lost_connection": True} + + print(self.data) def mod_sshd_config(self): # this disables dns lookup when connecting to EON to speed up commands from phantom app, reboot required diff --git a/selfdrive/phantom_receiver.py b/selfdrive/phantom/phantom_receiver.py similarity index 66% rename from selfdrive/phantom_receiver.py rename to selfdrive/phantom/phantom_receiver.py index 43b913c5f65b09..023913aca760b7 100644 --- a/selfdrive/phantom_receiver.py +++ b/selfdrive/phantom/phantom_receiver.py @@ -3,8 +3,7 @@ class PhantomReceiver: def __init__(self): - # self.phantom_data_sock = None - self.pm = None + self.pm = messaging_arne.PubMaster('phantomData') def receive_data(self, speed, angle, time): self.broadcast_data(True, speed, angle, time) @@ -17,14 +16,7 @@ def broadcast_data(self, status, speed, angle, time): phantom_data.phantomData.angle = angle phantom_data.phantomData.time = time self.pm.send('phantomData', phantom_data) - # self.phantom_data_sock.send(phantom_data.to_bytes()) - - def enable_phantom(self): - self.pm = messaging_arne.PubMaster('phantomData') - # self.phantom_data_sock = messaging_arne.pub_sock('phantomData') - return "ENABLED" # needed to tell the app we're all done with this function def disable_phantom(self): self.broadcast_data(False, 0.0, 0.0, 0.0) - self.phantom_data_sock.close() - return "DISABLED" + return 'DISABLED' From 8e602533fba346eab94693fe3626bd23eb4b4215 Mon Sep 17 00:00:00 2001 From: Shane Date: Mon, 18 Nov 2019 16:04:23 -0600 Subject: [PATCH 28/34] more submaster like :) --- selfdrive/phantom/phantom.py | 3 ++- selfdrive/phantom/{phantom_receiver.py => receiver.py} | 0 2 files changed, 2 insertions(+), 1 deletion(-) rename selfdrive/phantom/{phantom_receiver.py => receiver.py} (100%) diff --git a/selfdrive/phantom/phantom.py b/selfdrive/phantom/phantom.py index 2150894febd709..e852b29800cd64 100644 --- a/selfdrive/phantom/phantom.py +++ b/selfdrive/phantom/phantom.py @@ -28,7 +28,8 @@ def update(self): if time.time() - self.last_receive_time >= self.timeout and self.data['status']: self.data = {"status": True, "speed": 0.0, "angle": 0.0, "time": 0.0, "lost_connection": True} - print(self.data) + def __getitem__(self, s): + return self.data[s] def mod_sshd_config(self): # this disables dns lookup when connecting to EON to speed up commands from phantom app, reboot required diff --git a/selfdrive/phantom/phantom_receiver.py b/selfdrive/phantom/receiver.py similarity index 100% rename from selfdrive/phantom/phantom_receiver.py rename to selfdrive/phantom/receiver.py From ed96f67a6d1923ea129eaf994be5ae756c2eed71 Mon Sep 17 00:00:00 2001 From: Shane Date: Mon, 18 Nov 2019 16:43:36 -0600 Subject: [PATCH 29/34] updates to phantom --- cereal/arne182.capnp | 1 - selfdrive/controls/lib/long_mpc.py | 24 +++++++++++++++--------- selfdrive/phantom/phantom.py | 7 ++++--- selfdrive/phantom/receiver.py | 9 ++++----- 4 files changed, 23 insertions(+), 18 deletions(-) diff --git a/cereal/arne182.capnp b/cereal/arne182.capnp index 6444f65e0b2e9c..227705a0ba035a 100644 --- a/cereal/arne182.capnp +++ b/cereal/arne182.capnp @@ -33,7 +33,6 @@ struct PhantomData { status @0 :Bool; speed @1 :Float32; angle @2 :Float32; - time @3 :Float32; } struct ManagerData { diff --git a/selfdrive/controls/lib/long_mpc.py b/selfdrive/controls/lib/long_mpc.py index 77749f80fa7717..253f065d00403e 100644 --- a/selfdrive/controls/lib/long_mpc.py +++ b/selfdrive/controls/lib/long_mpc.py @@ -184,10 +184,10 @@ def process_phantom(self, lead): # if radar lead is available, ensure we use that as the real lead rather than ignoring it and running into it # todo: this is buggy and probably needs to be looked at x_lead = min(9.144, lead.dRel) - v_lead = min(self.phantom.data["speed"], v_lead) + v_lead = min(self.phantom["speed"], v_lead) else: x_lead = 9.144 - v_lead = self.phantom.data["speed"] + v_lead = self.phantom["speed"] return x_lead, v_lead def update(self, pm, CS, lead, v_cruise_setpoint): @@ -199,17 +199,23 @@ def update(self, pm, CS, lead, v_cruise_setpoint): # Setup current mpc state self.cur_state[0].x_ego = 0.0 - if self.phantom.data["status"]: - if self.phantom.data["speed"] != 0.0: + if self.phantom["status"]: + a_lead = 0.0 + if self.phantom["speed"] != 0.0: x_lead, v_lead = self.process_phantom(lead) - elif 'lost_connection' in self.phantom.data: - x_lead = 1.5 - v_lead = 0. # stop as quickly as possible + elif self.phantom.lost_connection: + x = [0, 14.3053] # 32 mph + y = [0.6096, 6.096] # 2, 20 feet + x_lead = interp(v_ego, x, y) + v_lead = max(v_ego - 4.4704, 0) # stop at a quick pace + x = [0, 14.3053] + y = [0, -2.2352] + a_lead = interp(v_ego, x, y) else: # else, smooth deceleration x_lead = 3.75 - v_lead = max(self.v_ego - (.7 / max(max(self.v_ego, 0) ** .4, .01)), 0.0) # smoothly decelerate to 0 todo: tune this! + v_lead = max(v_ego - 1.34112, 0) # smoothly decelerate to 0 + a_lead = -0.44704 - a_lead = 0.0 self.a_lead_tau = lead.aLeadTau self.new_lead = False if not self.prev_lead_status or abs(x_lead - self.prev_lead_x) > 2.5: diff --git a/selfdrive/phantom/phantom.py b/selfdrive/phantom/phantom.py index e852b29800cd64..36dd535bf65ca4 100644 --- a/selfdrive/phantom/phantom.py +++ b/selfdrive/phantom/phantom.py @@ -11,6 +11,7 @@ def __init__(self, timeout=1.): self.op_params = opParams() self.sm = messaging_arne.SubMaster('phantomData') self.data = {"status": False, "speed": 0.0} + self.lost_connection = False self.last_receive_time = time.time() self.timeout = timeout # in seconds if not travis and not self.op_params.get("UseDNS", None): # ensure we only run once @@ -19,14 +20,14 @@ def __init__(self, timeout=1.): def update(self): self.sm.update(0) phantom_data = self.sm['phantomData'] - self.data = {"status": phantom_data.status, "speed": phantom_data.speed, - "angle": phantom_data.angle, "time": phantom_data.time} + self.data = {"status": phantom_data.status, "speed": phantom_data.speed, "angle": phantom_data.angle} if self.sm.updated['phantomData']: self.last_receive_time = time.time() if time.time() - self.last_receive_time >= self.timeout and self.data['status']: - self.data = {"status": True, "speed": 0.0, "angle": 0.0, "time": 0.0, "lost_connection": True} + self.data = {"status": True, "speed": 0.0, "angle": 0.0} + self.lost_connection = True def __getitem__(self, s): return self.data[s] diff --git a/selfdrive/phantom/receiver.py b/selfdrive/phantom/receiver.py index 023913aca760b7..2568f2f53fee78 100644 --- a/selfdrive/phantom/receiver.py +++ b/selfdrive/phantom/receiver.py @@ -5,18 +5,17 @@ class PhantomReceiver: def __init__(self): self.pm = messaging_arne.PubMaster('phantomData') - def receive_data(self, speed, angle, time): - self.broadcast_data(True, speed, angle, time) + def receive_data(self, speed, angle): + self.broadcast_data(True, speed, angle) - def broadcast_data(self, status, speed, angle, time): + def broadcast_data(self, status, speed, angle): phantom_data = messaging_arne.new_message() phantom_data.init('phantomData') phantom_data.phantomData.status = status phantom_data.phantomData.speed = speed phantom_data.phantomData.angle = angle - phantom_data.phantomData.time = time self.pm.send('phantomData', phantom_data) def disable_phantom(self): - self.broadcast_data(False, 0.0, 0.0, 0.0) + self.broadcast_data(False, 0.0, 0.0) return 'DISABLED' From 41eab3859627855f7af6d3a08972451e78588beb Mon Sep 17 00:00:00 2001 From: Shane Date: Mon, 18 Nov 2019 16:53:54 -0600 Subject: [PATCH 30/34] updates to phantom --- selfdrive/controls/lib/long_mpc.py | 2 +- selfdrive/phantom/phantom.py | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/selfdrive/controls/lib/long_mpc.py b/selfdrive/controls/lib/long_mpc.py index 253f065d00403e..2676398280418c 100644 --- a/selfdrive/controls/lib/long_mpc.py +++ b/selfdrive/controls/lib/long_mpc.py @@ -34,7 +34,7 @@ def __init__(self, mpc_id): self.lead_data = {'v_lead': None, 'x_lead': None, 'a_lead': None} self.df_frame = 0 self.rate = 20 - self.phantom = Phantom(timeout=1.) + self.phantom = Phantom() self.last_cloudlog_t = 0.0 diff --git a/selfdrive/phantom/phantom.py b/selfdrive/phantom/phantom.py index 36dd535bf65ca4..10a7b90a6ad3c1 100644 --- a/selfdrive/phantom/phantom.py +++ b/selfdrive/phantom/phantom.py @@ -1,4 +1,3 @@ -import zmq import selfdrive.messaging_arne as messaging_arne from common.op_params import opParams import subprocess @@ -21,6 +20,7 @@ def update(self): self.sm.update(0) phantom_data = self.sm['phantomData'] self.data = {"status": phantom_data.status, "speed": phantom_data.speed, "angle": phantom_data.angle} + print(self.data) if self.sm.updated['phantomData']: self.last_receive_time = time.time() @@ -28,6 +28,10 @@ def update(self): if time.time() - self.last_receive_time >= self.timeout and self.data['status']: self.data = {"status": True, "speed": 0.0, "angle": 0.0} self.lost_connection = True + else: + self.lost_connection = False + + print(self.lost_connection) def __getitem__(self, s): return self.data[s] From 436b1ca4ec9a6ce21e79ed43e4f24f6367774ced Mon Sep 17 00:00:00 2001 From: Shane Date: Mon, 18 Nov 2019 17:01:35 -0600 Subject: [PATCH 31/34] final commit, ready to merge after testing --- selfdrive/phantom/phantom.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/selfdrive/phantom/phantom.py b/selfdrive/phantom/phantom.py index 10a7b90a6ad3c1..4b97e0c17cf384 100644 --- a/selfdrive/phantom/phantom.py +++ b/selfdrive/phantom/phantom.py @@ -20,7 +20,6 @@ def update(self): self.sm.update(0) phantom_data = self.sm['phantomData'] self.data = {"status": phantom_data.status, "speed": phantom_data.speed, "angle": phantom_data.angle} - print(self.data) if self.sm.updated['phantomData']: self.last_receive_time = time.time() @@ -31,8 +30,6 @@ def update(self): else: self.lost_connection = False - print(self.lost_connection) - def __getitem__(self, s): return self.data[s] From d610fd73edd35bb2581bf9acac575eada6d0985e Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Mon, 18 Nov 2019 23:21:19 -0600 Subject: [PATCH 32/34] Missed this --- selfdrive/controls/lib/long_mpc.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/selfdrive/controls/lib/long_mpc.py b/selfdrive/controls/lib/long_mpc.py index 2676398280418c..de95c72af52c36 100644 --- a/selfdrive/controls/lib/long_mpc.py +++ b/selfdrive/controls/lib/long_mpc.py @@ -142,8 +142,8 @@ def get_cost(self, TR): real_TR = self.lead_data['x_lead'] / float(self.v_ego) # switched to cost generation using actual distance from lead car; should be safer if abs(real_TR - TR) >= .25: # use real TR if diff is greater than x safety threshold TR = real_TR - if self.v_lead is not None and self.v_ego > 5: - factor = min(1,max(2,(self.v_lead - self.v_ego)/2 + 1.5)) + if self.lead_data['v_lead'] is not None and self.v_ego > 5: + factor = min(1,max(2,(self.lead_data['v_lead'] - self.v_ego)/2 + 1.5)) return min(round(float(interp(TR, x, y)), 3)/factor, 0.1) else: return round(float(interp(TR, x, y)), 3) From d200807a3e8bdb301e528967d86398d21b1afa12 Mon Sep 17 00:00:00 2001 From: Shane Date: Tue, 19 Nov 2019 01:19:40 -0600 Subject: [PATCH 33/34] fix auto updating and rebooting, fix segfaults caused by invalid syntax with the new messaging module --- selfdrive/car/toyota/carstate.py | 20 ++++++++++---------- selfdrive/controls/lib/pathplanner.py | 2 +- selfdrive/controls/lib/planner.py | 17 +++-------------- selfdrive/updated.py | 10 ++++------ 4 files changed, 18 insertions(+), 31 deletions(-) diff --git a/selfdrive/car/toyota/carstate.py b/selfdrive/car/toyota/carstate.py index 08c85b61674fe8..2360ec1603460c 100644 --- a/selfdrive/car/toyota/carstate.py +++ b/selfdrive/car/toyota/carstate.py @@ -218,8 +218,8 @@ def update(self, cp, cp_cam): self.gasbuttonstatus = 0 msg = messaging_arne.new_message() msg.init('arne182Status') - msg.gasbuttonstatus = self.gasbuttonstatus - msg.readdistancelines = cp.vl["PCM_CRUISE_SM"]['DISTANCE_LINES'] + msg.arne182Status.gasbuttonstatus = self.gasbuttonstatus + msg.arne182Status.readdistancelines = cp.vl["PCM_CRUISE_SM"]['DISTANCE_LINES'] if not travis: self.arne_pm.send('arne182Status', msg) if self.CP.carFingerprint == CAR.LEXUS_IS: @@ -315,19 +315,19 @@ def update(self, cp, cp_cam): dat = messaging_arne.new_message() dat.init('liveTrafficData') if self.spdval1 > 0: - dat.speedLimitValid = True + dat.liveTrafficData.speedLimitValid = True if self.tsgn1 == 36: - dat.speedLimit = self.spdval1 * 1.60934 + dat.liveTrafficData.speedLimit = self.spdval1 * 1.60934 elif self.tsgn1 == 1: - dat.speedLimit = self.spdval1 + dat.liveTrafficData.speedLimit = self.spdval1 else: - dat.speedLimit = 0 + dat.liveTrafficData.speedLimit = 0 else: - dat.speedLimitValid = False + dat.liveTrafficData.speedLimitValid = False if self.spdval2 > 0: - dat.speedAdvisoryValid = True - dat.speedAdvisory = self.spdval2 + dat.liveTrafficData.speedAdvisoryValid = True + dat.liveTrafficData.speedAdvisory = self.spdval2 else: - dat.speedAdvisoryValid = False + dat.liveTrafficData.speedAdvisoryValid = False if not travis: self.arne_pm.send('liveTrafficData', dat) diff --git a/selfdrive/controls/lib/pathplanner.py b/selfdrive/controls/lib/pathplanner.py index 6cf16591a039e3..39f0047ba6a5bb 100644 --- a/selfdrive/controls/lib/pathplanner.py +++ b/selfdrive/controls/lib/pathplanner.py @@ -142,6 +142,6 @@ def update(self, sm, pm, CP, VM): msg = messaging_arne.new_message() msg.init('latControl') - msg.anglelater = math.degrees(list(self.mpc_solution[0].delta)[-1]) + msg.latControl.anglelater = math.degrees(list(self.mpc_solution[0].delta)[-1]) if not travis: self.arne_pm.send('latControl', msg) diff --git a/selfdrive/controls/lib/planner.py b/selfdrive/controls/lib/planner.py index 3f8ae59643036f..ebfdba96f8ae39 100644 --- a/selfdrive/controls/lib/planner.py +++ b/selfdrive/controls/lib/planner.py @@ -97,10 +97,6 @@ class Planner(): def __init__(self, CP): self.CP = CP self.arne_sm = messaging_arne.SubMaster(['arne182Status', 'latControl']) - self.arne182 = None - self.lat_control = None - # self.arne182Status = messaging_arne.sub_sock('arne182Status', conflate=True) - # self.latcontolStatus = messaging_arne.sub_sock('latControl', conflate=True) self.mpc1 = LongitudinalMpc(1) self.mpc2 = LongitudinalMpc(2) @@ -149,15 +145,8 @@ def choose_solution(self, v_cruise_setpoint, enabled): self.v_acc_future = min([self.mpc1.v_mpc_future, self.mpc2.v_mpc_future, v_cruise_setpoint]) def update(self, sm, pm, CP, VM, PP): - self.arne182 = None - self.lat_control = None self.arne_sm.update(0) - self.arne182 = self.arne_sm['arne182Status'] - self.lat_control = self.arne_sm['latControl'] - if self.arne182 is None: - gas_button_status = 0 - else: - gas_button_status = self.arne182.gasbuttonstatus + gas_button_status = self.arne_sm['arne182Status'].gasbuttonstatus """Gets called when new radarState is available""" cur_time = sec_since_boot() v_ego = sm['carState'].vEgo @@ -167,10 +156,10 @@ def update(self, sm, pm, CP, VM, PP): angle_later = 0. else: steering_angle = sm['carState'].steeringAngle - if self.lat_control is None or v_ego < 11: + if v_ego < 11: angle_later = 0. else: - angle_later = self.lat_control.anglelater + angle_later = self.arne_sm['latControl'].anglelater if gas_button_status == 1: speed_ahead_distance = 150 diff --git a/selfdrive/updated.py b/selfdrive/updated.py index 386b92309787a6..b86cf283a3cf17 100755 --- a/selfdrive/updated.py +++ b/selfdrive/updated.py @@ -20,7 +20,7 @@ def main(gctx=None): params = Params() NEED_REBOOT = False - health_sock = messaging.sub_sock('health') + sm = messaging.SubMaster(['thermal', 'health']) # comma messaging still needs list even if it's just 1 service while True: # try network ping_failed = subprocess.call(["ping", "-W", "4", "-c", "1", "8.8.8.8"]) @@ -73,11 +73,9 @@ def main(gctx=None): params.put("LastUpdateTime", t.encode('utf8')) if NEED_REBOOT: - health = messaging.recv_sock(health_sock, wait=True) - if health is not None: - if not health.health.started: - NEED_REBOOT = False - os.system('reboot') + sm.update(1) + if not sm['thermal'].started and not (sm['health'].ignitionLine or sm['health'].ignitionCan): + os.system('reboot') time.sleep(30*60) From 439635eecd52ce5fc183ad7b9f1fd7a9d137dd1f Mon Sep 17 00:00:00 2001 From: Shane Date: Tue, 19 Nov 2019 02:58:39 -0600 Subject: [PATCH 34/34] - update mapd to use submaster and pubmaster. can revert if the logic doesn't work out - send fingerprint to sentry to debug --- selfdrive/car/car_helpers.py | 2 +- selfdrive/mapd/mapd.py | 38 ++++++++---------- selfdrive/mapd/messaging.py | 78 ------------------------------------ 3 files changed, 17 insertions(+), 101 deletions(-) delete mode 100644 selfdrive/mapd/messaging.py diff --git a/selfdrive/car/car_helpers.py b/selfdrive/car/car_helpers.py index 2a599ecea6f903..e9acbd3e85a420 100644 --- a/selfdrive/car/car_helpers.py +++ b/selfdrive/car/car_helpers.py @@ -134,7 +134,7 @@ def fingerprint(logcan, sendcan, has_relay): frame += 1 - cloudlog.warning("fingerprinted %s", car_fingerprint) + cloudlog.warning("fingerprinted {}".format({car_fingerprint: finger[0]})) params.put("CachedFingerprint", json.dumps([car_fingerprint, {int(key): value for key, value in finger[0].items()}])) return car_fingerprint, finger, vin diff --git a/selfdrive/mapd/mapd.py b/selfdrive/mapd/mapd.py index fd37fa41f3d218..47bcffa62be78a 100755 --- a/selfdrive/mapd/mapd.py +++ b/selfdrive/mapd/mapd.py @@ -9,18 +9,18 @@ #default_speeds_generator.main(DEFAULT_SPEEDS_BY_REGION_JSON_FILE) import time -import zmq import requests import threading import numpy as np import overpy -from cereal import arne182 from common.params import Params from collections import defaultdict from selfdrive.version import version, dirty from common.transformations.coordinates import geodetic2ecef -import selfdrive.mapd.messaging as messaging +import selfdrive.messaging_arne as messaging_arne +import selfdrive.messaging as messaging + from selfdrive.mapd.mapd_helpers import MAPS_LOOKAHEAD_DISTANCE, Way, circle_through_points, rate_curvature_points OVERPASS_API_URL = "https://z.overpass-api.de/api/interpreter" @@ -150,11 +150,9 @@ def save_gps_data(gps): def mapsd_thread(): global last_gps - context = zmq.Context() - poller = zmq.Poller() - gps_external_sock = messaging.sub_sock(context, 8032, poller, conflate=True) - map_data_sock = messaging.pub_sock(context, 8065) - traffic_data_sock = messaging.sub_sock(context, 8208, poller, conflate=True) + sm = messaging.SubMaster(['gpsLocationExternal', 'liveMapData']) + arne_sm = messaging_arne.SubMaster(['liveTrafficData']) + pm = messaging.PubMaster(['liveMapData']) cur_way = None curvature_valid = False @@ -172,14 +170,11 @@ def mapsd_thread(): speedLimittrafficvalid = False while True: - gps_ext = None - traffic = None - for socket, event in poller.poll(0): - if socket is gps_external_sock: - gps_ext = messaging.recv_one(socket) - elif socket is traffic_data_sock: - traffic = arne182.LiveTrafficData.from_bytes(socket.recv()) - if traffic is not None: + sm.update(0) + arne_sm.update(0) + gps_ext = sm['gpsLocationExternal'] + traffic = arne_sm['liveTrafficData'] + if True: # todo: should this be `if sm.updated['liveTrafficData']:`? if traffic.speedLimitValid: speedLimittraffic = traffic.speedLimit if abs(speedLimittraffic_prev - speedLimittraffic) > 0.1: @@ -194,9 +189,9 @@ def mapsd_thread(): speedLimittrafficAdvisoryvalid = False else: speedLimittrafficAdvisoryvalid = False - - if gps_ext is not None: - gps = gps_ext.gpsLocationExternal + + if sm.updated['gpsLocationExternal']: + gps = gps_ext else: continue @@ -296,7 +291,7 @@ def mapsd_thread(): dat = messaging.new_message() dat.init('liveMapData') - if last_gps is not None: + if last_gps is not None: # TODO: this should never be None with SubMaster now dat.liveMapData.lastGps = last_gps if cur_way is not None: @@ -352,8 +347,7 @@ def mapsd_thread(): dat.liveMapData.speedLimit = max_speed dat.liveMapData.mapValid = map_valid - - map_data_sock.send(dat.to_bytes()) + pm.send('liveMapData', dat) def main(gctx=None): diff --git a/selfdrive/mapd/messaging.py b/selfdrive/mapd/messaging.py deleted file mode 100644 index f5a1e55bc57dea..00000000000000 --- a/selfdrive/mapd/messaging.py +++ /dev/null @@ -1,78 +0,0 @@ -import zmq - -from cereal import log -from cereal import arne182 -from selfdrive.mapd import realtime - -def new_arne182_message(): - dat = arne182.Event.new_message() - dat.logMonoTime = int(realtime.sec_since_boot() * 1e9) - return dat - -def new_message(): - dat = log.Event.new_message() - dat.logMonoTime = int(realtime.sec_since_boot() * 1e9) - return dat - -def pub_sock(context, port, addr="*"): - sock = context.socket(zmq.PUB) - sock.bind("tcp://%s:%d" % (addr, port)) - return sock - -def sub_sock(context, port, poller=None, addr="127.0.0.1", conflate=False): - sock = context.socket(zmq.SUB) - if conflate: - sock.setsockopt(zmq.CONFLATE, 1) - sock.connect("tcp://%s:%d" % (addr, port)) - sock.setsockopt(zmq.SUBSCRIBE, b"") - if poller is not None: - poller.register(sock, zmq.POLLIN) - return sock - -def drain_sock(sock, wait_for_one=False): - ret = [] - while 1: - try: - if wait_for_one and len(ret) == 0: - dat = sock.recv() - else: - dat = sock.recv(zmq.NOBLOCK) - dat = log.Event.from_bytes(dat) - ret.append(dat) - except zmq.error.Again: - break - return ret - - -# TODO: print when we drop packets? -def recv_sock(sock, wait=False): - dat = None - while 1: - try: - if wait and dat is None: - dat = sock.recv() - else: - dat = sock.recv(zmq.NOBLOCK) - except zmq.error.Again: - break - if dat is not None: - dat = log.Event.from_bytes(dat) - return dat - -def recv_one(sock): - return log.Event.from_bytes(sock.recv()) - -def recv_one_arne182(sock): - return arne182.EventArne182.from_bytes(sock.recv()) - -def recv_one_or_none(sock): - try: - return log.Event.from_bytes(sock.recv(zmq.NOBLOCK)) - except zmq.error.Again: - return None - -def recv_one_or_none_arne182(sock): - try: - return arne182.EventArne182.from_bytes(sock.recv(zmq.NOBLOCK)) - except zmq.error.Again: - return None