Skocz do zawartości

Sebo_b

Społeczność Astropolis
  • Postów

    740
  • Dołączył

  • Ostatnia wizyta

Odpowiedzi opublikowane przez Sebo_b

  1. 1 minute ago, Behlur_Olderys said:

    Jakoś nie podoba mi się stosowanie raz long, raz unsigned long.

    Nie rozumiem, w którym miejscu?

     

    2 minutes ago, Behlur_Olderys said:

    gdzieś najprostszą protezę std::vector

    To jest oczywiście kolejny krok, wydzielenie kolekcji na zewnątrz. Ale z drugiej strony jest to taka prosta struktura, że można pominąć.

     

     

  2. 12 hours ago, r.ziomber said:

    Ale ja oczekuje krytyki! Chce sie uczyc od zawodowych programistow i doskonalic swoje znikome umiejetnosci.

    Jesli tylko masz czas napisac, z checia wyslucham, co zrobilem zle!

    Na szybko zrefaktorowałem Twój kod, a w sumie to napisałem go od nowa zachowując logikę. Nie testowałem tego kodu (tylko syntax), więc jest pewnie sporo bugów. Ale wyłapanie bugów to dobre ćwiczenie :)

     

    #include <limits.h>
    #include <cstdlib>
    
    class Timer {
    
    public:
    
    	typedef void(*Callback)(void*);
    
    	Timer();
    	~Timer();
    	/**
    	 * count < 0 for unlimited execution
    	 * returns task number or 0 if fail;
    	 **/
    	size_t addTask(long delay, long interval, int count, Callback callback, void* cbParam);
    	void removeTask(size_t taskId);
    
    	void run();
    
    	void cleanUp();
    
    private:
    
    	struct Task {
    		long interval;
    		unsigned long nextCall;
    		int count;
    		size_t taskId;
    
    		Callback cb;
    		void* cbParam;
    	};
    
    	Task* tasks;
    	size_t tasksSize;
    	size_t taskIdCounter;
    	bool clean;
    	unsigned long nextCall;
    
    };
    
    Timer::Timer():
    	tasks(NULL), tasksSize(0), clean(true), nextCall(ULONG_MAX), taskIdCounter(0)
    {
    }
    
    Timer::~Timer() {
    	if (tasks)
    		free(tasks);
    }
    
    size_t Timer::addTask(long delay, long interval, int count, Timer::Callback callback, void* cbParam) {
    
    	if (count == 0 || callback == NULL || interval == 0)
    		return 0;
    
    	Task *t = NULL;
    	unsigned long now = ::now();
    
    	if (!clean) {
    		for (size_t i = 0; i < tasksSize; ++i) {
    			if (tasks[i].count == 0) {
    				if (t == NULL) {
    					t = tasks+i;
    					clean = true;					
    				}
    				else {
    					clean = false;
    				}
    			}
    		}
    	}
    	else {
    
    		Task* newTasks = static_cast<Task*>(realloc(tasks,(tasksSize+1)*sizeof(Task)));
    		if (!newTasks)
    			return 0;
    		tasks = newTasks;
    		t = newTasks + tasksSize++;
    	}
    
    	t->interval = interval;
    	t->nextCall = now + interval + delay;
    	t->count = count;
    	t->cb = callback;
    	t->cbParam = cbParam;
    	t->taskId = ++taskIdCounter;
    
    	if ( static_cast<long>(nextCall - t->nextCall) >= 0)
    		nextCall = t->nextCall;
    
    	return t->taskId;
    }
    
    void Timer::removeTask(size_t taskId) {
    
    // we don't need to update nextCall, in the worst case we end up with one empty loop in run()
    //	unsigned long nextCallSoFar = ULONG_MAX;
    
    	for (size_t i = 0; i < tasksSize; ++i) {
    		if (tasks[i].taskId == taskId) {
    			tasks[i].count = 0;
    			clean = false;
    
    //			if ( nextCall != tasks[i].nextCall)
    				return;
    		}
    //		else if (static_cast<long>(nextCallSoFar - tasks[i].nextCall) >= 0) {
    //			nextCallSoFar = tasks[i].nextCall;
    //		}
    	}
    
    //	nextCall = nextCallSoFar;
    }
    
    void Timer::run() {
    
    	unsigned long now = ::now();
    
    	if ( static_cast<long>(now - nextCall) >= 0 ) {
    
    		for (size_t i = 0; i < tasksSize; ++i) {
    			
    			nextCall = ULONG_MAX;
    
    			if (tasks[i].count != 0 && static_cast<long>(now - tasks[i].nextCall) >= 0) {
    
    				tasks[i].cb( tasks[i].cbParam);
    
    				if (tasks[i].count > 0 && --tasks[i].count == 0)
    					clean = false;
    				else 
    					tasks[i].nextCall = now + tasks[i].interval;
    			}
    
    			if ( static_cast<long>(nextCall - tasks[i].nextCall) >= 0)
    				nextCall = tasks[i].nextCall;
    		}
    	}
    
    }
    
    void Timer::cleanUp() {
    
    	if (clean)
    		return;
    
    	Timer *head = tasks, *tail = tasks + tasksSize - 1;
    
    	while (head < tail) {
    
    		if (head->count == 0 && tail->count != 0) {
    			*head  = *tail;
    			tail->count = 0;
    		}
    
    		if (head->count != 0)
    			++head;
    		if (tail->count == 0)
    			--tail;
    	}
    
    	size_t newTasksSize = head-tasks;
    	Task* newTasks = static_cast<Task*>(realloc(tasks,newTasksSize*sizeof(Task)));
    	if (newTasks == NULL)
    		return;	// we basically keep it unclan
    
    	tasks = newTasks;
    	tasksSize = newTasksSize;
    	clean = true;
    }

     

    • Lubię 1
  3. Z tym co zaproponowane overflowy nie powinny mieć wpływu na średnie czasy - arytmetyka zadziała.

     

    1 minute ago, Behlur_Olderys said:

    static_cast wygląda najbardziej elegancko, ale znowu - muszę sam się przekonać :)

    Tutaj nie ma się co przekonywać, to trochę jak byś przyjechał z Anglii (pisanie w C) i twierdził, że musisz się przekonać do prawostronnego ruchu (C++) :) Piszesz w C++ to używać "pożądnych" castów. Co więcej, zaczniesz (lepiej nie) używać wielodziedziczenia i C casty się wysypią.

  4. 4 hours ago, r.ziomber said:

    przedzial czasu obejmujacy przekroczenie zakresu zmiennej

    Masz rację, że jest tam bug, a nawet dwa:

    1. Overflow nextCall - tak jak napisałeś, now() będzie duże, nextCall małe

    2. Overflow now() bo nie mamy pewności czy pod koniec zakresu zdąży się wykonać, czyli nextCall będzie duże, a now() małe

     

    To są dodatkowe cornercase'y, więc || a nie && w Twoim rozwiązaniu powinien to załatwić, tylko że pierwszy warunek zawiera się w tym co zaproponowałeś - więc wystarczyło by :

    if ( now() - nextCall < ULONG_MAX / 2 ) {
    
    // lub - bez dzielenia (choć to tylko estetyka w tym przypadku)
                                     
    if ( now() - nextCall < (ULONG_MAX >> 1) ) {
    
    // lub - moim zdaniem bardziej czytelnie
                                     
    if ( now() - nextCall < LONG_MAX )
      
    // lub - bez użycia limits
      
    if ( now() - nextCall < (~0ul >> 1) )
      
    // a ja bym napisał to tak, żeby było dla każdego czytelne (choć nie widać tak od razu, że obsługuje corner-case'y)
      
    if ( static_cast<long>(now() - nextCall) >= 0 ) {

     

    • Lubię 2
  5. 2 hours ago, Tayson said:

    Stackujesz w DSS? Mam nadzieję że w finalny stacku kanały RGB nie są zrownane. 

    Poprawna kalibracje koloru możesz uzyskać np eXcalibratorem + np nova astrometry net / upload + color combine w maximie. 

    Alternatywa to jeszcze np PixInsight płatny.  

    Pracuję na Macu - więc mam bardzo ograniczony wybór softu. Gdyby Pixinsight kosztował z połowę tego co kosztuje to bym się pewnie skusił, teraz sporo jeszcze przede mną zanim zacznę odczuwać braki w używanych toolach.

     

    2 hours ago, Tayson said:

    Bez stosowania masek w pewnym momencie zatrzymasz się w rozwoju i nie dasz ani kroka dalej. Twój wybór.... 

    Jeśli dojdę do tego momentu, to pewnie zacznę stosować. Po niedzieli wracam do Wawy i moje hobby się mocno ograniczy, jechać po 50-100km ze sprzętem i stać z pół nocy na zimnie samemu... pewnie znowu teleskop wyląduje w szafie na długie miesiące :(

     

    Podeszłem teraz inaczej, Nebulosity tylko stack + stretch, reszta w Affinity. Kanały są wszystkie, nawet niebieskie gwiazdki wyszły, tylko znowu jakieś takie niebiesko-zielone to zdjęcie. Trochę szumu tła zostawione specjalnie dla @Pav1007 :D

     

     

    m13_sq5.jpg

  6. 9 hours ago, Behlur_Olderys said:

    jest z tym dużo pracy dla programistów ostatnio

    Wciąż jest dużo, ale już coraz mniej. Oprócz pracy typowo dla elektronika: komórki od czasu iOSa i Androida to już nie embedded. Zostały telewizory, ale tam też coraz więcej Androida, więc jeśli nie pracujesz u SoC vendora (np MTK) to też nie embedded. Automotive się jeszcze broni rękami i nogami przed Googlem i Applem.

    • Lubię 1
  7. 3 minutes ago, piotr.d said:

    OK, ale co ja wtedy mogę zrobić?

    Na Synscanie poniżej align na 3 gwiazdy jest Polar Alignment. Działa to tak:

    1. Montaż ustawia się na jasnej gwieździe, np Arcturus

    2. Prosi o dokładne ustawienie jej w środku pola (pilotem). PS: nie wiem czy znasz tę metodę, ale jeśli nie masz okularu z krzyżem, to rozogniskowanie pomaga w ustawieniu obiektu centrycznie (jest po prostu dużym kółkiem w okularze).

    3. Przestawia o błąd w jednej osi i prosi o ustawienie śrubami (NIE pilotem).

    4. Robi to samo dla drugiej osi.

     

    Po tym trzeba znowu wyalignować na 3 gwiazdy. Czasem procedurę powtórzyć, żeby mieć jeszcze dokładniej.

     

    8 minutes ago, piotr.d said:

    Pozwolę sobie zadać jeszcze pytanie odnośnie tego żeby wiedzieć czy dobrze zrozumiałem. Załóżmy, że trafiłem na montaż idealny, który nie ma błędów

    Jeśli montaż będzie idealnie prowadził i będzie idealnie wypoziomowany - to obiekt będzie sztywno, niezależnie od alignowania. Alignowanie jest potrzebne tylko do GOTO*, procedurę alignowania można pominąć i kręcić ręcznie.

     

    * - nie mogę nigdzie znaleźć potwierdzenie / zaprzeczenia czy montaże SW EQ zawsze prowadzą tylko w jednej osi, czy może jak wykryje cone-error (brak poziomu) w czasie alignacji to pomaga sobie drugą osią. Mam podejrzenie, że sobie pomaga, bo wczoraj miałem żyletę na biegun (ustawiane softem) a obiekty po godzinie odjeżdżały, nie zauważyłem, że w menu był ustawiony cone-error z poprzednich alignów.

  8. 6 hours ago, Pav1007 said:

    Ja jednak proponuję zrobić zwykłego flata

    Nie mam flatownicy, sprzęt rozkładam po zmroku i składam przed świtem :( Więc posiłkuję się jak mogę. W drugiej próbie zrobiłem "ręcznie" syntetycznego flata.

     

    Dziś nauczyłem się jeszcze jednego, obrabiać należy w nocy / wieczorem, a nie w bardzo słoneczny dzień ;)

     

    Jak teraz?

     

    m13_sq4.thumb.jpg.4032550d4407024b27196cac8787c0c0.jpg

  9. 9 minutes ago, Pav1007 said:

    Masz świetną skalę na ten obiekt.

    Dzięki - mam jeszcze większa z asi290mc, jak uda mi się porządnie to złożyć to może nałożę sam środek.

     

    Co do "paprochów", to chyba znalazłem, synthetic flat fielder z Nebulosity dość mocno to wycina. Złożę na spokojnie jeszcze raz. Dzięki wszystkim za komentarze.

  10. 49 minutes ago, RomekAstrobaza said:

    Aby czy na pewno?

    Na pewno. Patrzyłem na Twoje zdjęcie przed publikacją - masz tam większy FOV, ale 1:1 każda punktowa (nie szare tło) gwiazda u Ciebie występuje też u mnie. Tylko @Pav1007 jak zwykle ma rację, że za bardzo pojechałem z tłem, dlatego się dość bardzo odcięły, niektóre mają po kilka pixeli.

     

    Załączam porównanie Twojego zdjęcia do mojego - 1:1 crop ze środka, nic nie modyfikowane.

     

    EDIT: forum wycina animowane PNG, wrzucam GIFa.

     

    ezgif.com-apng-to-gif.gif

    • Lubię 1
  11. 2 minutes ago, wessel said:

    A gwiazdki nakładasz stemplem, to nie jest dobry pomysł

    Nie nałożyłem żadnej gwiazdki stemplem. Jestem też przeciwnikiem masek - choć tutaj dla dwóch placków zrobiłem wyjątek.

  12. Dość oklepany obiekt, ale chciałem go powtórzyć w szerszym polu (wiem, i tak wąskie).

     

    Łapane wczoraj, księżyc prawie 90% ale o 23:30 już dość nisko, bo 10 st.

     

    MN190 / EQ6-R / Canon 40D / ISO400 / 120x30s + darki.

     

    EDIT: Po żywej dyskusji w wątku i pomocy wielu forowiczów (dzięki) podmieniam zdjęcie na trochę lepsze. Do ideału daleko - ale na razie muszę odpocząć od tego obiektu. Może się przesiądę na czarnobiałą kamerę bez filtrów :)

     

    m13_sq6.jpg

  13. 1 hour ago, Behlur_Olderys said:

     

    Ciekawe, chyba masz rację z tym timeAwaited, ciekawe co się stanie jak tak napiszę :) Może w weekend znajdę trochę czasu...

    Ale operatory przesunięcia w Twoim kodzie jakoś mnie zniechęcają strasznie :)

    Może za mało embedded kodu widziałeś :) Można to owrapować w define'y - ale moim zdaniem wtedy nie jest czytelne. Jak usuniesz delta, bo myślę, że z nią to przesadziłem (zrób testy na sprzęcie, sam jestem ciekaw) - to kod się uprasza do kilku linii i imo jest mega czytelny.

     

    Oczywiście założenie jest, że chcesz mieć jak najdokładniej zachowany czas całej sekwencji, a nie różnicę pomiędzy wywołaniami.

     

    // constructor
    nextCall = now() + interval;
    
    //active loop
    if ( nextCall < now() ) {
      nextCall += interval;
      callWhatever();
    }

     

    • Lubię 1
  14. 1 hour ago, sidiouss said:

    STMy z DMA

    Schodzimy coraz niżej :)

     

    Co do samego kodu, dość pokrętnie napisane, np:

    
    m_timeStart = timeNow;
    // leftover = timeNow - m_timeAwaited
    // in SetAwaitedTime
    m_timeAwaited = (unsigned long)(m_timeStart + m_interval - leftover);
    
    // so
    m_timeAwaited = m_interval + m_timeAwaited

    Propozycja:

    // constructor
    nextCall = now() + interval;
    delta = 0;
    
    //active loop
    unsigned long n = now();
    if (nextCall - (delta >> 8) < n) {
      nextCall += interval;
      delta = ( (abs(nextCall - n) << 7) + (delta*4) )/5;  // old delta is weighted 4, new delta is weighted 1, this needs to be checked on hardware to determine right weights
      
      
      callWhatever();
    }

    W zaproponowanym rozwiązaniu:

    - kolejne czasy liczę zawsze od bazowego (nextCall += interval), więc niedokładności wywołań nie wpływają na kolejne wywołania,

    - kod jest odporny na przepełnienia, po prostu arytmetyka zadziała,

    - gdyby stosować proste if (nextCall < n to czasy odchylały by się zawsze w jedną stronę, było by spóźnienie, stąd delta która odchyla to w stronę przeciwną

    - delta za każdym razem się koryguje (średnia ważona, waga 4 na starą wartość, waga 1 na nową)

    - delta ma 8 bitów dokładności po przecinku, nowa jest przesuwana o 7 bitów bo interesuje nas połowa delty żeby rozłożyć czasu równomiernie po obu stronach

    - jeśli na Arduino mnożenie i dzielenie jest drogie (nie wiem tego) to *4 można zamienić na << 2

     

    Nie kompilowałem/debuggowałem/testowałem tego kodu, więc ręki nie dam sobie uciąć, że wszystko działa poprawnie - ale pokazuje o co chodzi.

     

    EDIT: ta delta może być przedwczesną optymalizacją - bez tego pewnie średnio zadziała tak samo dobrze. 

     

    • Lubię 1
×
×
  • Dodaj nową pozycję...

Powiadomienie o plikach cookie

Umieściliśmy na Twoim urządzeniu pliki cookie, aby pomóc Ci usprawnić przeglądanie strony. Możesz dostosować ustawienia plików cookie, w przeciwnym wypadku zakładamy, że wyrażasz na to zgodę.