Related
I working one a small Java project controlling a DMX-light, a “moving head”.
So far, I can control the moving head using Art-Net, doing the most simple stuff – like setting a value for a channel.
Now I’m working on moving the moving head. The moving head supports 16bit and this troubles me. I know that the 16bit comes from using two “channels”. 1 channel is one byte, 8 bits, so the maximum value for 1 channel is 255. When using two channels the maximum increases to 65.356 which will give much more precise movement on the pan- & tilt-channel. So, a 16bit moving head uses 4 channels for controlling pan and tilt.
Now I want to create a simple movement generator in Java. Simple looping the pan- and tilt-value from 1 to 255. If I understand it correct, when using 16bit moving head, it means, first setting the pan “fine” (pan only in this example) from 1 to 255 and when pan “fine” reaches 255 then increasing pan “course” with 1, like this:
Pan “fine” 1->255, when reaching 255 increase pan course with 1 then again Pan “fine” 1->255, when reaching 255 increase pan course with 1 and then again Pan “fine” 1->255, when reaching 255 increase pan course with 1, and so on.
I need to have some kind of delay in the movement generator and I can see on various places that it is best to avoid Thread.sleep() (and while loops) as it can drift, so I have decided to built the generator in its own method and then call this method with an Executor Service (scheduleAtFixedRate), like this:
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class Main {
public static void main(String[] args) {
test test = new test();
ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
executorService.scheduleAtFixedRate(test::run, 0, 10000000, TimeUnit.NANOSECONDS);
}
}
“run” is the method with the generator and “test” is the class containing the method. That part is working well.
This is the method in test which should serve as the movement generator:
public class test {
int start = 1;
int end = 255;
int counterFine = 1;
int counterCourse = 255;
boolean startOverCourse = false;
public void run() {
if (!startOverCourse) {
counterFine++;
}
if (startOverCourse) {
counterFine--;
}
if (counterFine == end) {
counterCourse++;
}
if (counterCourse == end) {
startOverCourse = true;
counterFine = end;
}
}
}
Yes, I know it is not much to give you, sorry for that, but I can't figure out what to do now and the reason is this:
When “course” reaches (I starts at 1, and increases with 1 when “fine” reaches 255) 255, course will need to start to count down, 255 becoming 254 and so on. But, that will also mean that when course reaches 255 then fine also have to decrease, going from 255-> (before it was 1->255).
Maybe some of you guys can figure out what I want to archive, maybe I’m doing it complete wrong, then please tell me how to approach it.
So, in Java, how to do a simple Pan & Tilt movement generator using 16bit. I know how to do it in 8 bit, using two channels, but I don’t know how to include the fine-channels and making it 16bit.
Kind Regards 😊
EDIT:
This is what my test class look like now:
public class test {
DmxValues dmxValuesOBJ;
SendArtnet SendArtnet;
int start = 1;
int end = 255;
int counterFine = 1;
int counterCourse = 1;
boolean startOverCourse = false;
test(DmxValues obj1, SendArtnet obj2) {
dmxValuesOBJ = obj1;
SendArtnet = obj2;
}
public void run() {
dmxValuesOBJ.setdmxvalues(4 - 1, counterFine);
dmxValuesOBJ.setdmxvalues(2 - 1, counterFine);
SendArtnet.testSend();
if (counterFine == end && !startOverCourse) {
dmxValuesOBJ.setdmxvalues(3 - 1, counterCourse);
dmxValuesOBJ.setdmxvalues(1 - 1, counterCourse);
SendArtnet.testSend();
counterCourse++;
}
if (counterFine == end && startOverCourse) {
dmxValuesOBJ.setdmxvalues(3 - 1, counterCourse);
dmxValuesOBJ.setdmxvalues(1 - 1, counterCourse);
SendArtnet.testSend();
counterCourse--;
}
if (counterFine == end) {
counterFine = start;
}
if (counterCourse == end) {
startOverCourse = true;
}
if (counterCourse == start) {
startOverCourse = false;
}
System.out.println(counterFine);
counterFine++;
}
}
SendArtnet and DmxValues are classes for sending and containing the dmx-data, should not be relevant, it's there so I can see in my dmx-monitor what is going on.
Above test class does what I want when it comes to the course-value (counterCourse), goes up to 255 and down to 1. The issue is I can not figure out how to do the same with the fine value (counterfine) - now it runs in one direction (from 1 to 255) but I need it to change direction when countercourse reaches 255, from 255 to 1.
I hate all those "if" - any smarter way to do all this?
Conceptually, you're trying to smoothly ramp a single 16 bit value (between 0 and 65535), and the two 8-bit values are simply a way of expressing that data in a way that works with DMX512. Trying to express the ramping/counting in terms of separate coarse and fine counters is complicating the logic significantly since you're essentially implementing your own arithmetic carry, in a way.
Keep a single counter, sweep it between 0 and 65535 (or your range of interest), and convert it at each step: the coarse part is counter / 256, and the fine part is counter % 256.
I'm trying to figure out how to increase the speed of this algorithm. It works perfectly for two games (2-person games, CPU vs Human), but the problems is when I assign more than three piles (that contains a number of stones, so each player can pick up more than one), the computer player takes forever to compute the moves:
public Object[] minimax(int depth, int player) {
if(hasPlayer1Won(player)){
return new Object[]{get_default_input(1),1};
}else if(hasPlayer2Won(player)){
return new Object[]{get_default_input(1),-1};
}
List<T> movesAvailable = getNextStates();
if(movesAvailable.isEmpty()){
return new Object[]{get_default_input(0), 0};
}
int min = Integer.MAX_VALUE;
int max = Integer.MIN_VALUE;
T computersMove = getNextStates().get(0);
int i = 0;
for (T move: movesAvailable) {
makeAMove(move, player);
Object[] result = minimax(depth + 1, player == G.PLAYER1 ? G.PLAYER2 : G.PLAYER1);
int currentScore = (int)result[1];
if(player == G.PLAYER1){
max = Math.max(currentScore, max);
if(currentScore >= 0 && depth == 0) {
computersMove = move;
}
if(currentScore == 1){
resetMove(move);
break;
}
if(i==movesAvailable.size() - 1 && max < 0){
if (depth == 0){
computersMove = move;
}
}
}else{
min = Math.min(currentScore, min);
if(min == -1) {
resetMove(move);
break;
}
}
i++;
resetMove(move);
}
return new Object[]{computersMove, player == G.PLAYER1 ? max: min};
}
I have sucessfully tested the following methods for improving minimax (used it to play Tic-Tac-Toe and Domineering):
Alpha beta pruning - used a special variant of this type of pruning, in conjunction with Lazy evaluation - basically instead of generating the whole tree I just generated an optimal move on each layer and kept Lazy holders for the other state-action pairs (applying the Lazy evaluation method, by making use of a supplier and calling it when a move different than the one I held was made).
Heuristic pruning - see the chapter on heuristics in that book. I basically only generated the first d branches of the tree and instead of having a deterministic outcome, I applied the heuristic function described in that book to the current state to determine a heuristic outcome. Whenever move (d+1) was made, I generated another branch using the same approach.
Here, d is the level that you choose (safest way is by testing)
Parallel computing also have a look at this, you may find it harder to implement but it pays off
First 2 options brought me a lot of computational time save, such that I was able to play Domineering optimally up to a 5x5 board and heuristically up to 10x10 (it can be better depending on how well you want it to play).
I am learning to implement some of the more simple algorithms in Java, but I can't figure out why this statement works:
private void doMergeSort(int lowerIndex, int higherIndex) {
if (lowerIndex < higherIndex) {
int middle = lowerIndex + (higherIndex - lowerIndex) / 2;
doMergeSort(lowerIndex, middle);
doMergeSort(middle + 1, higherIndex);
mergeParts(lowerIndex, middle, higherIndex);
}
}
I have gone through debug, and I don't understand how it is possible that the second instance of doMergeSort is called - doMergeSort(middle + 1, higherIndex); - when the final iteration of the previous doMergeSort is feeding 0, 0 into the method. Wouldn't that cause the if statement to return false, and the second doMergeSort call not to execute?
This code does run, and the result is correct, but how is this possible?
I think the source of your confusion is it sounds like you think that the variables for lowerIndex, middle and higherIndex get modfied across recursive calls. They don't. Each recursive call gets it's own separate copy of those fields so the 2nd call to doMergeSort(middle + 1, higherIndex); doesn't use updated middle and higherIndex, it uses whatever those values were when they were passed into doMergeSort(int lowerIndex, int higherIndex)
So if were to print what the variables at each call were, they would look something like this...
doMergeSort(0,9)
doMergeSort(0,4)
doMergeSort(0,2)
doMergeSort(0,1)
doMergeSort(0,0)
doMergeSort(1,1)
mergeParts(0,0,1)
doMergeSort(2,2)
mergeParts(0,1,2)
doMergeSort(3,4)
doMergeSort(3,3)
doMergeSort(4,4)
mergeParts(3,3,4)
mergeParts(0,2,4)
doMergeSort(5,9)
doMergeSort(5,7)
doMergeSort(5,6)
doMergeSort(5,5)
doMergeSort(6,6)
mergeParts(5,5,6)
doMergeSort(7,7)
mergeParts(5,6,7)
doMergeSort(8,9)
doMergeSort(8,8)
doMergeSort(9,9)
mergeParts(8,8,9)
mergeParts(5,7,9)
mergeParts(0,4,9)
There is nothing to do for sequences of 0 or 1 items: they are already ordered.
So it doesn't matter (and is arguably correct) if the the function returns immediately in this cases. The behavior also forms the base-case - when the sequence cannot be divided further.
I think running through an example might be best.
Let's assume the initial call is to doMergeSort(0, 3) [lowerIndex = 0, higherIndex = 3].
In this call, middleIndex will be 1 [0 + (3-0)/2]
This results in the following call:
doMergeSort(0, 1) and doMergeSort(2,3).
Looking at doMergeSort(0,1), we get the following calls:
doMergeSort(0, 0) and doMergeSort(1, 1) [lowerIndex = 0, middleIndex = 0, higherIndex = 1]
Since in both doMergeSort(0, 0) [lowerIndex = 0, higherIndex = 0] and doMergeSort(1,1) [lowerIndex = 1, higherIndex = 1], lowerIndex is not less than higherIndex, it returns right away.
Now let's look at doMergeSort(2,3) [Similar logic as above]:
It results in the call doMergeSort(2, 2) and doMergeSort(3, 3) which also returns right away due to the same reason as above [lowerIndex is not less than higherIndex]
as dkatlez pointed out, i believe your confusion comes from the fact that the variables lowerIndex and higherIndex get modified in the later recursive call.
Let's analyse what happen to trivial case, when lowerIndex is lower than higherIndex by 1:
doMergeSort(3, 4);
private void doMergeSort(int lowerIndex = 3, int higherIndex = 4) {
if (3 < 4) { // true
int middle = 3 + (4 - 3) / 2; // 3.5 truncated to int -> 3
doMergeSort(3, 3); // when you call method with lowerIndex == higherIndex
// first command is "if (3 < 3)" which is false and no
// code inside "if" is running. Your program exits from
// the method and runs next command
doMergeSort(3 + 1 = 4, 4); // same case as previous command
mergeParts(3, 3, 4);
}
}
All this happened because of two things:
Difference between lowerIndex and higherIndex is getting lower in every iteration;
Method doMergeSort has a boundary condition which allows to stop recursion.
recently I've been trying to teach myself a bit of recursion to understand the process better. While I understand basic recursion techniques, I still struggle quite a bit with the idea of recursive backtracking. In order to help this, I've attempted to program a method that solves a sudoku solver when given a 2D array and and two ints, r and c, which are meant to represent the current column and row.
I have everything set up properly I believe, yet I can't quite figure out how to handle the "unraveling", or what happens after my initial method calls reach the eventual base case.
As of right now, when I run this method, it just returns a board that's empty, (unless there was previously a value there before, in which case it remains unchanged). I feel like the "board[r][c] = 0" that I have at the end of the method might have something to do with that.
The method "digitsValid" corresponds to a method that checks to make sure the current location on the board is a valid move within the row, column, and 3x3 subgrid.
Any help would be much appreciated.
private boolean sudokuSolver(int[][] board, int r, int c) {
if(c > 8) {
c = 0;
r = r + 1;
}
if(r > 8) {
return true;
}
if(board[r][c] != 0) {
sudokuSolver(board, r, c + 1);
} else {
for(int i = 1; i <= 9; i++) {
if(digitsValid(board, r, c)) {
board[r][c] = i;
if(sudokuSolver(board, r, c + 1)) {
return true;
}
}
}
}
board[r][c] = 0;
return false;
}
I think your original assessment is correct. Recursive methods sound confusing but think of them like this:
public class RecursiveTest{
public static void main(String[] args){
int x = 5;
recursiveMethod(x);
}
public static void recursiveMethod(int i){
System.out.println("Method just started for i = " + i);
if(i > 0)
recursiveMethod(i - 1);
System.out.println("Method just ended for i = " + i);
}
}
Yields the following output:
Method just started for i = 5
Method just started for i = 4
Method just started for i = 3
Method just started for i = 2
Method just started for i = 1
Method just started for i = 0
Method just ended for i = 0
Method just ended for i = 1
Method just ended for i = 2
Method just ended for i = 3
Method just ended for i = 4
Method just ended for i = 5
Explanation
A recursive method is not all that different from any other method. It executes some code, at some point calls a method, runs that method and then continues running the rest of the code and finishes where any other method would finish.
The only difference is that method call is a call to itself. This would work the same as if you had copy-pasted that same method 5 times and named it all something different and then "daisy chained" them together.
In the example above, the original value is 5, it prints out that it started the for i=5, then ran the same method with the value of 4. Printed that, then ran 3 etc. Once it reached the final value where i = 0 the if statement failed and therefore it stopped the recursive calls. The method we are currently in (i = 0) finishes by writing Method just ended for i = 0 then it returns to the calling method when i = 1 and back tracks the same way it went in.
Your Code
I'm not quite sure what you have going on here. Does your example work? I'd like to see the isValid() method, but the following code you have:
for(int i = 1; i <= 9; i++) { // Runs the following code 9 times.
if(digitsValid(board, r, c)) { // if true once, true every time
board[r][c] = i;
if(sudokuSolver(board, r, c + 1)) { // this is a totally separate method
return true;
}
}
}
Your loop runs 9 times. The if statement following it never changes. The values within are not edited within the loop, so if it evaluates to true when i = 1 then it's going to evaluate to true on all 9 iterations of the for loop. This means the value at board[r][c] is going to end on 9.
From the looks of it, the only way this will ever return false, is if there is an invalid digit already stored in the array at the time of calling the method.
I am converting a some C++ to java and have a small bit that I am unsure about
first question is what is tested for in the line
if (ampconst[i][0] || ampconst[i][1])
this in an example to the data in the array.
static short ampconst[NUT_SERIES][2] = {
{0,0},
{0,0},
{46,-24}
};
and my second question is that the ampsecul array is far shorter than NUT_SERIES
so I am getting array out of bounds exceptions, the array terminates like so
static long ampsecul[][5] = {
{0 ,-171996 ,-1742 ,92025 ,89},
{1 ,2062 ,2 ,-895 ,5},
{8 ,-13187 ,-16 ,5736 ,-31},
{9 ,1426 ,-34 ,54 ,-1},
{10 ,-517 ,12 ,224 ,-6},
{11 ,217 ,-5 ,-95 ,3},
{12 ,129 ,1 ,-70 ,0},
{15 ,17 ,-1 ,0 ,0},
{17 ,-16 ,1 ,7 ,0},
{30 ,-2274 ,-2 ,977 ,-5},
{31 ,712 ,1 ,-7 ,0},
{32 ,-386 ,-4 ,200 ,0},
{33 ,-301 ,0 ,129 ,-1},
{37 ,63 ,1 ,-33 ,0},
{38 ,-58 ,-1 ,32 ,0},
/* termination */ { -1, }
};
so how could this be handled in java and what would the values be at these lines
when the array is out of bounds or how would C++ handle this.
ampsin = ampsecul[isecul][1] + ampsecul[isecul][2] * T10;
ampcos = ampsecul[isecul][3] + ampsecul[isecul][4] * T10;
thanks in advance for any advice.
This is the whole for loop too see the code in context.
for (i = isecul = 0; i < NUT_SERIES ; ++i) {
double arg = 0., ampsin, ampcos;
short j;
if (ampconst[i][0] || ampconst[i][1]) {
/* take non-secular terms from simple array */
ampsin = ampconst[i][0];
ampcos = ampconst[i][1];
} else {
/* secular terms from different array */
ampsin = ampsecul[isecul][1] + ampsecul[isecul][2] * T10;
ampcos = ampsecul[isecul][3] + ampsecul[isecul][4] * T10;
++isecul;
}
for (j = 0; j < 5; ++j)
arg += delcache[j][NUT_MAXMUL + multarg[i][j]];
if (fabs(ampsin) >= prec)
lastdpsi += ampsin * sin(arg);
if (fabs(ampcos) >= prec)
lastdeps += ampcos * cos(arg);
}
if (ampconst[i][0] || ampconst[i][1])
tests whether the first/second column in ampconst[i] contain non-zero (it is an early-out optimization: if both the constants are 0 then the calculation can be skipped)
Edit I just found (google!) that this is a nutation calculation that has been adopted in quite a few places, but seems to be originally from a libastro.
hg clone https://bitbucket.org/brandon/pyephem
As far as the isecul index is concerned: apparently isecul should never grow to >= 15 (note that i is the loop variable, not isecul, isecul is incremented conditionally).
However, seeing the 'terminator' (-1) value, I'd really expect a check some like
if (ampsecul[isecul][0] == -1)
isecul = 0; // ? just guessing :)
or
if (ampsecul[isecul][0] == -1)
break;
Also, I get the impression that the first column of ampsecul is a range-based division, so somehow, there would be a binarysearch for the matching slot into ampsecul, not direct indexing (i.e. isecul=4 would select index 2 (2..8) not 4)
Are you sure you are getting the source code correctly? I looks very much like there are some custom indexers (operators[](...)) that you misssed out on? This would probably be about the same class/function that contains the terminator check like shown above.
Edit from the linked source I get the impression that the code is very much intended as is, and hence isecul should simply not be growing >= 15
That first if statement is testing the array entries for zero/non-zero. In C/C++ a boolean is simply an int that is used in a special way such that zero is false and non-zero is true.
As for your second array question I haven't grocked it yet. But understand that C/C++ does no array bounds checking (other than what may accidentally occur if you touch an undefined storage page), so unless there's an egregious error in the C++ code there must be something that limits references to the valid bounds of the array.