Turning Motor on Lego NXT returns error 0002EA Type 2 - robot

I a writing a program using RobotC for the Lego NXT to imitate the behaviour of a puppy. This section of code is supposed to rotate the head which is connected to motor port 3 and read the value on the ultra sonic sensor. If while the head is turned, the dog is called, it will turn in the direction it was already facing. The following function is called when the ultrasonic sensor reads a value (meaning the robot has come close to a wall):
visible
void SonarSensor()
{
int sensorValleft;
int sensorValright;
bool alreadyTurned = false;
int i,j;
i = 0;
j = 0;
motor[1] = 0;
motor[2] = 0;
motor[3] = -SPEED/2;
wait10Msec(15);
motor[3] = 0;
sensorValleft = SensorValue[3];
while(i<100)
{
if(SensorValue[4] > 40)//calibrate sound sensor
{
//turn left
motor[1]=SPEED;
motor[2] = -SPEED;
wait10Msec(25);
i = 1000;
j = 1000;
alreadyTurned = true;
}
else
{
i++;
wait1Msec(5);
}
}
motor[3] = SPEED/2;
wait10Msec(30);
motor[3] = 0;
sensorValright = SensorValue[3];
while(j<100)
{
if(SensorValue[3] > 1)//calibrate sound sensor
{
//turn right
motor[1]-=SPEED;
motor[2] = SPEED;
wait10Msec(25);
j = 1000;
alreadyTurned = true;
}
else
{
j++;
wait1Msec(5);
}
}
if(alreadyTurned == false)
{
if(sensorValleft > sensorValright)
{
//turn left
motor[1]=SPEED;
motor[2] = -SPEED;
wait10Msec(25);
}
else
{
//turn right
motor[1]=-SPEED;
motor[2] = SPEED;
wait10Msec(25);
}
}
}visible
When the head (motor[3]) rotates the first time the error 0002EA Type2 appears on the NXT screen. At first we thought it was because we were over-rotating the motor causing it to be obstructed so we tried to play around with the wait times but it made no difference.
Any ideas on what causes this error or how to fix it would be appreciated.
Thanks,
Dominique

The answer as to why only motor[3] causes an error is actually quite simple. The motorA, motorB, and motorC values are defined in an enum, where motorA=0, motorB=1, and motorC=2. So, motor[1] and motor[2] are equivalent to calling motor[motorB] and motor[motorC]. However, motor[3] isn't equivalent to anything. It's trying to set the power of a motor that doesn't exist. motor[0] would be ok, however, and would correspond to motor[motorA].

While debugging, I started putting break points in to see where the error was and it alwas occurred on the line motor[3] = -SPEED/2; it turns out that with the third motor the proper syntax is to use motor[motorA]=-SPEED/2;. I am not sure why only this motor returns this error as I am using two other motors which I set new speeds using
motor[1]=SPEED;
motor[2]=SPEED;
However, this was the way to abolish the error.

Related

Best way to do object collision?

I'm trying to do wall collision for objects and I've followed a tutorial that offers one method of doing collision.
This is the tutorial: https://www.youtube.com/watch?v=yZU1QJJdxgs
Currently, if the object detects a wall, instead of moving it's full distance, it moves pixel by pixel until it's against the wall. This worked well until I started trying to rotate the object with image_rotate, because it caused objects to get stuck in walls by either sliding against them or if they rotated into them.
I fixed this by using draw_sprite_ext instead and changing the rotation of the sprite itself and not the mask, which worked for about 20 minutes until it started causing more problems.
///obj_player Step
//Initialise Variables
hor_speed = 0;
ver_speed = 0;
accelerationspeed = 0.2;
decelerationspeed = 0.2;
maxspeed = 3;
pointdirection = 0;
//Get player's input
key_right = keyboard_check(ord("D"))
key_left = -keyboard_check(ord("A"))
key_up = -keyboard_check(ord("W"))
key_down = keyboard_check(ord("S"))
pointdirection = point_direction(x,y,mouse_x,mouse_y) + 270
hor_movement = key_left + key_right;
ver_movement = key_up + key_down;
//horizontal acceleration
if !(abs(hor_speed) >= maxspeed) {
hor_speed += hor_movement * accelerationspeed;
}
//horizontal deceleration
if (hor_movement = 0) {
if !(hor_speed = 0) {
hor_speed -= (sign(hor_speed) * decelerationspeed)
}
}
//vertical acceleration
if !(abs(ver_speed) >= maxspeed) {
ver_speed += ver_movement * accelerationspeed;
}
//vertical deceleration
if (ver_movement = 0) {
if !(ver_speed = 0) {
ver_speed -= (sign(ver_speed) * decelerationspeed)
}
}
//horizontal collision
if (place_meeting(x+hor_speed,y,obj_wall)) {
while(!place_meeting(x+sign(hor_speed),y,obj_wall)) {
x += sign(hor_speed);
}
hor_speed = 0;
}
//vertical collision
if (place_meeting(x,y+ver_speed,obj_wall)) {
while(!place_meeting(x,y+sign(ver_speed),obj_wall)) {
y += sign(ver_speed);
}
ver_speed = 0;
}
//move the player
x += hor_speed;
y += ver_speed;
///obj_player Draw
//rotate to look at cursor
draw_sprite_ext(spr_player, 0, x,y,image_xscale,image_yscale, pointdirection, image_blend, image_alpha);
I think the best way to rotate objects is through image_rotate, and I'd like to do it without getting stuff stuck in walls. Can my current method of collision be adapted to do this, or should I attempt to do it in a different way?
Your code looks fine, but if you're going to be rotating objects then you would also need to consider having a "knock back mechanic." Reason being is the player could be sitting next to this wall and if you rotate the object over them so they cant move, its not a fun time being stuck.
So you 'could' have the object that's rotating do a check before rotating and if objects are in the way then either stop it or push them back so they cant be within range.

Sprite Smooth movement and facing position according to movement

i'm trying to make this interaction with keyboard for movement using some sprites and i got stuck with two situations.
1) The character movement is not going acording to the animation itself (it only begin moving after one second or so while it's already being animated). What i really want it to do is, to move without a "initial acceleration feeling" that i get because of this problem
2) I can't think of a way to make the character face the position it should be facing when the key is released. I'll post the code here, but since it need images to work correctly and is not so small i made a skecth available at this link if you want to check it out: https://www.openprocessing.org/sketch/439572
PImage[] reverseRun = new PImage [16];
PImage[] zeroArray = new PImage [16];
void setup(){
size(800,600);
//Right Facing
for(int i = 0; i < zeroArray.length; i++){
zeroArray[i] = loadImage (i + ".png");
zeroArray[i].resize(155,155);
}
//Left Facing
for( int z = 0; z < reverseRun.length; z++){
reverseRun[z] = loadImage ( "mirror" + z + ".png");
reverseRun[z].resize(155,155);
}
}
void draw(){
frameRate(15);
background(255);
imageMode(CENTER);
if(x > width+10){
x = 0;
} else if (x < - 10){
x = width;}
if (i >= zeroArray.length){
i = 3;} //looping to generate constant motiion
if ( z >= reverseRun.length){
z = 3;} //looping to generate constant motiion
if (isRight) {
image(zeroArray[i], x, 300);
i++;
} //going through the images at the array
else if (isLeft) {
image(reverseRun[z],x,300);
z++;
} going through the images at the array
else if(!isRight){
image(zeroArray[i], x, 300);
i = 0; } //"stoped" sprite
}
}
//movement
float x = 300;
float y = 300;
float i = 0;
float z = 0;
float speed = 25;
boolean isLeft, isRight, isUp, isDown;
void keyPressed() {
setMove(keyCode, true);
if (isLeft ){
x -= speed;
}
if(isRight){
x += speed;
}
}
void keyReleased() {
setMove(keyCode, false);
}
boolean setMove(int k, boolean b) {
switch (k) {
case UP:
return isUp = b;
case DOWN:
return isDown = b;
case LEFT:
return isLeft = b;
case RIGHT:
return isRight = b;
default:
return b; }
}
The movement problem is caused by your operating system setting a delay between key presses. Try this out by going to a text editor and holding down a key. You'll notice that a character shows up immediately, followed by a delay, followed by the character repeating until you release the key.
That delay is also happening between calls to the keyPressed() function. And since you're moving the character (by modifying the x variable) inside the keyPressed() function, you're seeing a delay in the movement.
The solution to this problem is to check which key is pressed instead of relying solely on the keyPressed() function. You could use the keyCode variable inside the draw() function, or you could keep track of which key is pressed using a set of boolean variables.
Note that you're actually already doing that with the isLeft and isRight variables. But you're only checking them in the keyPressed() function, which defeats the purpose of them because of the problem I outlined above.
In other words, move this block from the keyPressed() function so it's inside the draw() function instead:
if (isLeft ){
x -= speed;
}
if(isRight){
x += speed;
}
As for knowing which way to face when the character is not moving, you could do that using another boolean value that keeps track of which direction you're facing.
Side note: you should really try to properly indent your code, as right now it's pretty hard to read.
Shameless self-promotion: I wrote a tutorial on user input in Processing available here.

game maker GML twin stick shooter analogue controller

I am trying to make a twin stick shooter but I cannot get right analogue stick to shoot in the correct direction. Here is the code I have the weapon sits on top of the player and rotates. It all works fine just need to know how to get the correct angle of the right stick and fire a bullet in that direction.
//set depth
depth = -y + obj_player.y_off_set - 1;
//analog left stick face direction
var h_point = gamepad_axis_value(0, gp_axisrh);
var v_point = gamepad_axis_value(0, gp_axisrv);
if ((h_point != 0) || (v_point != 0))
{
var pdir = point_direction(0, 0, h_point, v_point);
var dif = angle_difference(pdir, image_angle);
image_angle += median(-20, dif, 20);
}
//flips gun when turning
if(gamepad_axis_value(0, gp_axisrh) < -0.5)
{
image_yscale = -1;
}else if (gamepad_axis_value(0, gp_axisrh) > 0.5)
{
image_yscale = 1;
}
//fireing
fire = gamepad_button_check_pressed(0, gp_shoulderr) && alarm[0] <= 0;
if(fire)
{
var face = point_direction(0, 0, gp_axisrh, gp_axisrv);
var p = instance_create(x, y, obj_projectile);
var xforce = lengthdir_x(20, face*90);
var yforce = lengthdir_x(20, face*90);
p.creator = id;
with (p){
physics_apply_impulse(x, y, xforce, yforce);
}
as this question is a couple months old, I imagine you found the solution to your problem, but hopefully this answer can help anyone else stuck on the issue.
Based on the code snippet you provided, it looks like if you remove the *90 from the lengthdir_ functions, your code should work.
Here is the code I wrote in my game to get 360 degree shooting working with the right analog stick (this code lives in the step event of the Player object):
if (shooting) {
bullet = instance_create(x, y, Bullet);
with (bullet) {
haxis = gamepad_axis_value(0, gp_axisrh);
vaxis = gamepad_axis_value(0, gp_axisrv);
dir = point_direction(0, 0, haxis, vaxis);
physics_apply_impulse(x, y, lengthdir_x(50, gp_axisrh), lengthdir_y(50, dir));
}
}
This particular thread on the GameMaker community forums was quite helpful as I researched how to solve this issue in my game.

Vulkan depth image binding error

Hi I am trying to bind depth memory buffer but I get an error saying as below. I have no idea why this error is popping up.
The depth format is VK_FORMAT_D16_UNORM and the usage is VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT. I have read online that the TILING shouldnt be linear but then I get a different error. Thanks!!!
The code for creating and binding the image is as below.
VkImageCreateInfo imageInfo = {};
// If the depth format is undefined, use fallback as 16-byte value
if (Depth.format == VK_FORMAT_UNDEFINED) {
Depth.format = VK_FORMAT_D16_UNORM;
}
const VkFormat depthFormat = Depth.format;
VkFormatProperties props;
vkGetPhysicalDeviceFormatProperties(*deviceObj->gpu, depthFormat, &props);
if (props.linearTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) {
imageInfo.tiling = VK_IMAGE_TILING_LINEAR;
}
else if (props.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) {
imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
}
else {
std::cout << "Unsupported Depth Format, try other Depth formats.\n";
exit(-1);
}
imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
imageInfo.pNext = NULL;
imageInfo.imageType = VK_IMAGE_TYPE_2D;
imageInfo.format = depthFormat;
imageInfo.extent.width = width;
imageInfo.extent.height = height;
imageInfo.extent.depth = 1;
imageInfo.mipLevels = 1;
imageInfo.arrayLayers = 1;
imageInfo.samples = NUM_SAMPLES;
imageInfo.queueFamilyIndexCount = 0;
imageInfo.pQueueFamilyIndices = NULL;
imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
imageInfo.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
imageInfo.flags = 0;
// User create image info and create the image objects
result = vkCreateImage(deviceObj->device, &imageInfo, NULL, &Depth.image);
assert(result == VK_SUCCESS);
// Get the image memory requirements
VkMemoryRequirements memRqrmnt;
vkGetImageMemoryRequirements(deviceObj->device, Depth.image, &memRqrmnt);
VkMemoryAllocateInfo memAlloc = {};
memAlloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
memAlloc.pNext = NULL;
memAlloc.allocationSize = 0;
memAlloc.memoryTypeIndex = 0;
memAlloc.allocationSize = memRqrmnt.size;
// Determine the type of memory required with the help of memory properties
pass = deviceObj->memoryTypeFromProperties(memRqrmnt.memoryTypeBits, 0, /* No requirements */ &memAlloc.memoryTypeIndex);
assert(pass);
// Allocate the memory for image objects
result = vkAllocateMemory(deviceObj->device, &memAlloc, NULL, &Depth.mem);
assert(result == VK_SUCCESS);
// Bind the allocated memeory
result = vkBindImageMemory(deviceObj->device, Depth.image, Depth.mem, 0);
assert(result == VK_SUCCESS);
Yes, linear tiling may not be supported for depth usage Images.
Consult the specification and Valid Usage section of VkImageCreateInfo. The capability is queried by vkGetPhysicalDeviceFormatProperties and vkGetPhysicalDeviceImageFormatProperties commands. Though depth formats are "opaque", so there is not much reason to use linear tiling.
This you seem to be doing in your code.
But the error informs you that you are trying to use a memory type that is not allowed for the given Image. Use vkGetImageMemoryRequirements command to query which memory types are allowed.
Possibly you have some error there (you are using 0x1 which is obviously not part of 0x84 per the message). You may want to reuse the example code in the Device Memory chapter of the specification. Provide your memoryTypeFromProperties implementation for more specific answer.
I accidentally set the typeIndex to 1 instead of i and it works now. In my defense I have been vulkan coding the whole day and my eyes are bleeding :). Thanks for the help.
bool VulkanDevice::memoryTypeFromProperties(uint32_t typeBits, VkFlags
requirementsMask, uint32_t *typeIndex)
{
// Search memtypes to find first index with those properties
for (uint32_t i = 0; i < 32; i++) {
if ((typeBits & 1) == 1) {
// Type is available, does it match user properties?
if ((memoryProperties.memoryTypes[i].propertyFlags & requirementsMask) == requirementsMask) {
*typeIndex = i;// was set to 1 :(
return true;
}
}
typeBits >>= 1;
}
// No memory types matched, return failure
return false;
}

How can i change background color in a while loop - processing

I'm new to processing and trying to make a very simple program where i have an arduino that produces a seriel input (according to an analogue read value). The idea is a Processing window will open with a block color shown for 30 seconds. In this time all the readings from the arduino will be summed and averaged - creating an average for that color.
After 30 seconds the colour will change and a new average (for the next color) will start being calculated. This is the code i have started to write (for now focusing on just one 30 second period of green).
I realise there are likely problems with the reading/summing and averaging (i havent researched these yet so i'll put that to one side) - but my main question is why isn't the background green? When i run this program i expect the background to be green for 30 seconds - where as what happens is it is white for 30 seconds then changes to green. Can't figure out why! Thanks for any help!
import processing.serial.*;
Serial myPort;
float gsrAverage;
float greenAverage;
int gsrValue;
int greenTotal = 0;
int greenCount = 1;
int timeSinceStart = 0;
int timeAtStart;
int count=0;
color green = color(118,236,0);
void setup () {
size(900, 450);
// List all the available serial ports
//println(Serial.list());
myPort = new Serial(this, Serial.list()[0], 9600);
}
void draw () {
while (timeSinceStart < 30000) {
background(green);
greenTotal = greenTotal + gsrValue;
greenCount = greenCount + 1;
delay(500);
timeSinceStart = millis()-timeAtStart;
//println(timeSinceStart); for de bugging
}
greenAverage = greenTotal/greenCount;
//println(greenAverage); for de bugging
}
void serialEvent (Serial myPort) {
int inByte=myPort.read();
//0-255
gsrValue=inByte;
}
What I like to do for timers, is use IF statements and use millis() or a constantly updated variable 'm' right inside the condition:
int timeSinceStart;
int m;
void setup(){
timeSinceStart = millis(); // initialize here so it only happens once
}
void draw(){
m = millis(); // constantly update the variable
if(timeSinceStart + 30000 < m){
greenAverage = greenTotal/greenCount; // or whatever is outside while loop
timeSinceStart = millis();
}
//Anything that went inside the while loop can go here, or above the IF
}
This makes it so around every 30 seconds, the background will change once, and you just re-update the timeSinceStart variable in there too. This way, it will only update when you want it to update and not constantly update and break the code.
I tend not to use while loops in processing as they usually cause headaches. Hope my example helps.
May have found a way round this using an IF statement. I perhaps looked over the fact the draw function is itself a loop, so i was able to use a variation of
if (timeSinceStart < 5000) {
background(green);
}
within draw.
When dealing with timed events in Processing you should not use while loops inside the draw() function. The draw() function itself is a while loop which updates the "screen" each frame.
So, what you should do is create a timer and let it do a switch for you inside the draw() function. In your case, if you want to start with a green screen, you do that in the setup() function, and then create a method for altering according to a timer in your draw() function.
This is a suggestion on how you could solve your particular problem. Just change the cycle variable according to your need. In your case it would be 30000.
boolean isGreen = true;
int startTime = 0;
int lastTime = 0;
int cycle = 1000; //the cycle you need
void setup() {
size(200, 200);
background(0, 255, 0); //green
}
void draw() {
startTime = millis();
if (startTime > lastTime + cycle) {
if (isGreen) {
background(255); //white
isGreen = !isGreen;
} else {
background(0, 255, 0); //green
isGreen = !isGreen;
}
lastTime = millis();
}
}