PDA

View Full Version : Arbotix 0.5.0



lnxfergy
07-24-2011, 01:53 PM
0.5.0 is out! I recommend anyone using the ArbotiX drivers to switch to the 0.5.0/latest tag, as trunk is about to get a bit refactored in preparation for 1.0 push. This is the last release targeted at Diamondback, as future releases will be targeted awesome arm control using new features from the Electric release. Changes in 0.5.0 are:


[arbotix_firmware] various updates to clean up and speed up firmware.
[arbotix_python] add startup code to wait for connection.
[arbotix_python] remove PML support.
[arbotix_python] added terminal program.
[arbotix_controllers] new gripper controller.

You can checkout the code using:
svn co http://vanadium-ros-pkg.googlecode.com/svn/tags/arbotix/latest (http://vanadium-ros-pkg.googlecode.com/svn/tags/arbotix/0.4.0) arbotix

-Fergs

lnxfergy
07-25-2011, 12:52 PM
I've also tagged an 0.1.0 release of simple_arms which works with 0.5.0 of ArbotiX.

-Fergs

Pi Robot
09-30-2011, 06:57 PM
Hey Fergs,

I am trying to get the latest version of ros-electric-arbotix to work with a USB2Dynamixel controller but at launch time I simply get a list of "Waiting for response..." messages and the driver never connects to the controller. The USB2Dynamixel itself is OK because I can connect to it using the dynamixel_motor stack.

My YAML file looks like this:


port: /dev/ttyUSB0
baud: 1000000
rate: 20
sync_write: False
sync_read: False
read_rate: 20
write_rate: 20

dynamixels: {
shoulder_pan_joint: {id: 1, neutral: 512, max_speed: 100, min_angle: -145, max_angle: 145, invert: False},
shoulder_lift_joint: {id: 2, neutral: 512, max_speed: 100, invert: True},
elbow_flex_joint: {id: 3, neutral: 512, max_speed: 100, invert: True},
wrist_flex_joint: {id: 4, neutral: 512, max_speed: 100, min_angle: -90, max_angle: 90, invert: True},
gripper_joint: {id: 5, neutral: 512, max_speed: 100, min_angle: -20, max_angle: 25, invert: False},
head_pan_joint: {id: 6, neutral: 512, max_speed: 100, min_angle: -145, max_angle: 145, invert: False},
head_tilt_joint: {id: 7, neutral: 512, max_speed: 100, min_angle: -90, max_angle: 90, invert: False}
}
controllers: {
head_controller: {action_name: head_follow_joint_trajectory, type: follow_controller, joints: [head_pan_joint, head_tilt_joint]},
arm_controller: {type: follow_controller, joints: [shoulder_pan_joint, shoulder_lift_joint, elbow_flex_joint, wrist_flex_joint]}
}

Thanks!
patrick

lnxfergy
09-30-2011, 07:51 PM
Patrick,

I've committed a patch in trunk, you'll also have to set "onboard: False" for each of your controllers.

-Fergs

Pi Robot
09-30-2011, 08:17 PM
Thanks Fergs,

After updating to your patch I can now connect to the USB2Dynamixel and move the servos with controllerGUI.py. However, I am seeing only 0's on /joint_states so that, for example, interactive_markers won't work in RViz. My current YAML looks like this:


port: /dev/ttyUSB0
baud: 1000000
rate: 20
sync_write: False
sync_read: False
read_rate: 20
write_rate: 20

dynamixels: {
shoulder_pan_joint: {id: 1, neutral: 512, max_speed: 100, min_angle: -145, max_angle: 145, invert: False},
shoulder_lift_joint: {id: 2, neutral: 512, max_speed: 100, invert: True},
elbow_flex_joint: {id: 3, neutral: 512, max_speed: 100, invert: True},
wrist_flex_joint: {id: 4, neutral: 512, max_speed: 100, min_angle: -90, max_angle: 90, invert: True},
gripper_joint: {id: 5, neutral: 512, max_speed: 100, min_angle: -20, max_angle: 25, invert: False},
head_pan_joint: {id: 6, neutral: 512, max_speed: 100, min_angle: -145, max_angle: 145, invert: False},
head_tilt_joint: {id: 7, neutral: 512, max_speed: 100, min_angle: -90, max_angle: 90, invert: False}
}
controllers: {
head_controller: {onboard: False, action_name: head_follow_joint_trajectory, type: follow_controller, joints: [head_pan_joint, head_tilt_joint]},
arm_controller: {onboard: False, type: follow_controller, joints: [shoulder_pan_joint, shoulder_lift_joint, elbow_flex_joint, wrist_flex_joint]}
}

--patrick

lnxfergy
09-30-2011, 08:27 PM
Whoops... pull latest and try again (As you can guess, I rarely test with a USB2Dynamxiel).

-Fergs

Pi Robot
09-30-2011, 08:37 PM
Bingo! I'm all set. Thanks for the light-speed turnaround.

--patrick

MatthewGP
07-16-2012, 08:19 PM
Hi,

I recently purchased an Arbotix controller and Arm kit with 2 dynamixel servos for controlling a Microsoft Lifecam. I have been going through these sites:
https://code.google.com/p/vanadium-ros-pkg/
https://code.google.com/p/arbotix/
https://code.google.com/p/robocontroller/
https://groups.google.com/forum/?fromgroups#!forum/robocontroller (https://groups.google.com/forum/?fromgroups#%21forum/robocontroller)
http://www.ros.org/wiki/arbotix
http://www.pirobot.org/blog/

Unfortunately, I am getting terribly confused. I see that for the ROS-PKGs that you have tags up to .6.2 and then in Trunk, I am not even sure... Typically if I were to pull a new setup I would pull from trunk, but I can't quite tell if I should in this case.

Also, on the Arbotix site, I see the recommended 0014 is quite a bit older than a lot of what is in trunk.

Ultimately, I was able to get everything working with Arduino 023 and RoboRealm. However, my plan is to use ROS so that I can add an Asus Xtion and additional sensors and equipment going forward. This is where I am getting stuck a bit.

I am running Ubuntu 12.04 and have ROS Fuerte installed. I have been able to get the LifeCam working with OpenCV. I have the Arbotix Package installed. I finally got a copy of .6.1 firmware installed after modifying it to work with Arduino 1.01

Here is the ros.pde:

/*
ArbotiX Firmware for ROS driver
Copyright (c) 2008-2011 Vanadium Labs LLC. All right reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of Vanadium Labs LLC nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL VANADIUM LABS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

/* Build Configuration */
#define USE_BASE // Enable support for a mobile base
#define USE_HW_SERVOS // Enable only 2/8 servos, but using hardware control

#define CONTROLLER_COUNT 5
/* Hardware Constructs */
#include <ax12.h>
#include <BioloidController.h>
BioloidController controllers[CONTROLLER_COUNT];

#include "ros.h"

#ifdef USE_HW_SERVOS
#include <HServo.h>
HServo servos[2];
int servo_vals[2]; // in millis
#else
#include <Servo.h>
Servo servos[10];
int servo_vals[10]; // in millis
#endif

#ifdef USE_BASE
#ifdef USE_BIG_MOTORS
#include <BigMotors.h>
BigMotors drive = BigMotors();
#else
#include <Motors2.h>
Motors2 drive = Motors2();
#endif
#include <EncodersAB.h>
#include "diff_controller.h"
#endif

/* Register Storage */
unsigned char baud = 7; // ?
unsigned char ret_level = 1; // ?
unsigned char alarm_led = 0; // ?

/* Pose & Sequence Structures */
typedef struct{
unsigned char pose; // index of pose to transition to
int time; // time for transition
} sp_trans_t;
int poses[30][AX12_MAX_SERVOS]; // poses [servo_id-1]
sp_trans_t sequence[50]; // sequence
int seqPos; // step in current sequence

/*
* Setup Functions
*/
#if defined(AX_RX_SWITCHED)
void scan(){
// do a search for devices on the RX bus, default to AX if not found
int i;
for(i=0;i<AX12_MAX_SERVOS;i++){
dynamixel_bus_config[i] = 1;
if(ax12GetRegister(i+1, AX_ID, 1) != (i+1)){
dynamixel_bus_config[i] = 0;
}
}
}
#endif
void setup(){
Serial.begin(115200);
ax12Init(1000000);

#ifdef USE_BASE
Encoders.Begin();
setupPID();
#endif

// note: ARBOTIX_PLUS and SERVO_STIK are defined in our Bioloid library.
#if defined(AX_RX_SWITCHED)
delay(1000);
scan();
#endif

pinMode(0,OUTPUT); // status LED
}

/*
* Handle Write Requests to ArbotiX Registers
*/
unsigned char handleWrite(){
int addr = params[0]; // address to write
int bytes = length-3; // # of bytes left to write
int k = 1; // index in parameters of value to write
while(bytes > 0){
if(addr < REG_BAUD_RATE){
return INSTRUCTION_ERROR;
}else if(addr == REG_BAUD_RATE){
UBRR1L = params[k];
}else if(addr < REG_RESCAN){
// write digital
int pin = addr - REG_DIGITAL;
#ifdef SERVO_STIK
pin = 31-pin;
#endif
if(params[k] & 0x02) // high
digitalWrite(pin, HIGH);
else
digitalWrite(pin, LOW);
if(params[k] & 0x01) // output
pinMode(pin, OUTPUT);
else
pinMode(pin, INPUT);
}else if(addr == REG_RESCAN){
#if defined(AX_RX_SWITCHED)
scan();
#endif
}else if(addr == REG_RETURN_LEVEL){
ret_level = params[k];
}else if(addr == REG_ALARM_LED){
// TODO:
}else if(addr < REG_SERVO_BASE){
return INSTRUCTION_ERROR; // error - analog are read only
}else if(addr < REG_MOVING){
// write servo
int s = addr - REG_SERVO_BASE;
#ifdef USE_HW_SERVO
if( s >= 4 ){
#else
if( s >= 20){
#endif
return INSTRUCTION_ERROR;
}else{
if( s%2 == 0 ){ // low byte
s = s/2;
servo_vals[s] = params[k];
}else{ // high byte
s = s/2;
servo_vals[s] += (params[k]<<8);
if(servo_vals[s] > 500 && servo_vals[s] < 2500){
servos[s].writeMicroseconds(servo_vals[s]);
if(!servos[s].attached())
servos[s].attach(s);
}else if(servo_vals[s] == 0){
servos[s].detach();
}
}
}
}else{
return INSTRUCTION_ERROR;
}
addr++;k++;bytes--;
}
return 0;
}

int handleRead(){
int checksum = 0;
int addr = params[0];
int bytes = params[1];
unsigned char v;
while(bytes > 0){
if(addr == REG_MODEL_NUMBER_L){
v = 44;
}else if(addr == REG_MODEL_NUMBER_H){
v = 1; // 300
}else if(addr == REG_VERSION){
v = 0;
}else if(addr == REG_ID){
v = 253;
}else if(addr == REG_BAUD_RATE){
v = 34; // 56700
}else if(addr < REG_RETURN_LEVEL){
// send digital read
if(addr == REG_DIGITAL){
// 0->7
#ifdef SERVO_STIK
v = PINA;
#else
v = PINB;
#endif
}else if(addr == REG_DIGITAL+1){
// 8-15
#ifdef SERVO_STIK
v = (PINB>>1);
#else
v = PIND;
#endif
}else{
// 16-23
v = PIND;
}
}else if(addr == REG_RETURN_LEVEL){
v = ret_level;
}else if(addr == REG_ALARM_LED){
// TODO
}else if(addr < REG_SERVO_BASE){
// send analog reading
v = analogRead(addr-REG_ANA_BASE)>>2;
}else if(addr < REG_MOVING){
// send servo position
v = 0;
}else{
v = 0;
}
checksum += v;
Serial.print(v);
addr++;bytes--;
}
return checksum;
}

int doPlaySeq(){
seqPos = 0; int i;
while(sequence[seqPos].pose != 0xff){
int p = sequence[seqPos].pose;
// are we HALT?
if(Serial.read() == 'H') return 1;
// load pose
for(i=0; i<controllers[0].poseSize; i++)
controllers[0].setNextPose(i+1,poses[p][i]);
controllers[0].interpolateSetup(sequence[seqPos].time);
while(controllers[0].interpolating)
controllers[0].interpolateStep();
// next transition
seqPos++;
}
return 0;
}

/*
* Send status packet
*/
void statusPacket(int id, int err){
Serial.print(0xff);
Serial.print(0xff);
Serial.print(id);
Serial.print(2);
Serial.print(err);
Serial.print(255-((id+2+err)%256));
}

/*
* decode packets: ff ff id length ins params checksum
* same as ax-12 table, except, we define new instructions for Arbotix
*/
void loop(){
int i;

// process messages
while(Serial.available() > 0){
// We need to 0xFF at start of packet
if(mode == 0){ // start of new packet
if(Serial.read() == 0xff){
mode = 2;
digitalWrite(0,HIGH-digitalRead(0));
}
//}else if(mode == 1){ // another start byte
// if(Serial.read() == 0xff)
// mode = 2;
// else
// mode = 0;
}else if(mode == 2){ // next byte is index of servo
id = Serial.read();
if(id != 0xff)
mode = 3;
}else if(mode == 3){ // next byte is length
length = Serial.read();
checksum = id + length;
mode = 4;
}else if(mode == 4){ // next byte is instruction
ins = Serial.read();
checksum += ins;
index = 0;
mode = 5;
}else if(mode == 5){ // read data in
params[index] = Serial.read();
checksum += (int) params[index];
index++;
if(index + 1 == length){ // we've read params & checksum
mode = 0;
if((checksum%256) != 255){
// return an error packet: FF FF id Len Err=bad checksum, params=None check
statusPacket(id,CHECKSUM_ERROR);
}else if(id == 253){ // ID = 253, ArbotiX instruction
switch(ins){
case AX_WRITE_DATA:
// send return packet
statusPacket(id,handleWrite());
break;

case AX_READ_DATA:
checksum = id + params[1] + 2;
Serial.print(0xff);
Serial.print(0xff);
Serial.print(id);
Serial.print(2+params[1]);
Serial.print(0);
// send actual data
checksum += handleRead();
Serial.print(255-((checksum)%256));
break;

case ARB_SIZE_POSE: // Pose Size = 7, followed by single param: size of pose
statusPacket(id,0);
if(controllers[0].poseSize == 0)
controllers[0].setup(18);
controllers[0].poseSize = params[0];
controllers[0].readPose();
break;

case ARB_LOAD_POSE: // Load Pose = 8, followed by index, then pose positions (# of param = 2*pose_size)
statusPacket(id,0);
for(i=0; i<controllers[0].poseSize; i++)
poses[params[0]][i] = params[(2*i)+1]+(params[(2*i)+2]<<8);
break;

case ARB_LOAD_SEQ: // Load Seq = 9, followed by index/times (# of parameters = 3*seq_size)
statusPacket(id,0);
for(i=0;i<(length-2)/3;i++){
sequence[i].pose = params[(i*3)];
sequence[i].time = params[(i*3)+1] + (params[(i*3)+2]<<8);
}
break;

case ARB_PLAY_SEQ: // Play Seq = A, no params
statusPacket(id,0);
doPlaySeq();
break;

case ARB_LOOP_SEQ: // Play Seq until we recieve a 'H'alt
statusPacket(id,0);
while(doPlaySeq() > 0);
break;

// ARB_TEST is deprecated and removed

case ARB_CONTROL_SETUP: // Setup a controller
statusPacket(id,0);
if(params[0] < CONTROLLER_COUNT){
controllers[params[0]].setup(length-3);
for(int i=0; i<length-3; i++){
controllers[params[0]].setId(i, params[i+1]);
}
#ifdef USE_BASE
}else if(params[0] == 10){
Kp = params[1];
Kd = params[2];
Ki = params[3];
Ko = params[4];
#endif
}
break;

case ARB_CONTROL_WRITE: // Write values to a controller
statusPacket(id,0);
if(params[0] < CONTROLLER_COUNT){
for(int i=0; i<length-4; i+=2){
controllers[params[0]].setNextPose(controllers[params[0]].getId(i/2), params[i+1]+(params[i+2]<<8));
}
controllers[params[0]].readPose();
controllers[params[0]].interpolateSetup(params[length-3]*33);
#ifdef USE_BASE
}else if(params[0] == 10){
left_speed = params[1];
left_speed += (params[2]<<8);
right_speed = params[3];
right_speed += (params[4]<<8);
if((left_speed == 0) && (right_speed == 0)){
drive.set(0,0);
ClearPID();
}else{
if((left.Velocity == 0) && (right.Velocity == 0)){
PIDmode = 1; moving = 1;
left.PrevEnc = Encoders.left;
right.PrevEnc = Encoders.right;
}
}
left.Velocity = left_speed;
right.Velocity = right_speed;
#endif
}
break;

case ARB_CONTROL_STAT: // Read status of a controller
if(params[0] < CONTROLLER_COUNT){
Serial.print(0xff);
Serial.print(0xff);
Serial.print(id);
Serial.print(3);
Serial.print(0);
checksum = controllers[params[0]].interpolating;
Serial.print(checksum);
checksum += id + 3;
Serial.print(255-((checksum)%256));
#ifdef USE_BASE
}else if(params[0] == 10){
checksum = id + 2 + 8;
Serial.print(0xff);
Serial.print(0xff);
Serial.print(id);
Serial.print(2+8);
Serial.print(0); // error level
int v = ((unsigned long)Encoders.left>>0)%256;
Serial.print(v);
checksum += v;
v = ((unsigned long)Encoders.left>>8)%256;
Serial.print(v);
checksum += v;
v = ((unsigned long)Encoders.left>>16)%256;
Serial.print(v);
checksum += v;
v = ((unsigned long)Encoders.left>>24)%256;
Serial.print(v);
checksum += v;
v = ((unsigned long)Encoders.right>>0)%256;
Serial.print(v);
checksum += v;
v = ((unsigned long)Encoders.right>>8)%256;
Serial.print(v);
checksum += v;
v = ((unsigned long)Encoders.right>>16)%256;
Serial.print(v);
checksum += v;
v = ((unsigned long)Encoders.right>>24)%256;
Serial.print(v);
checksum += v;
Serial.print(255-((checksum)%256));
#endif
}
break;

}
}else if(id == 0xFE){
// sync read or write
if(ins == ARB_SYNC_READ){
int start = params[0]; // address to read in control table
int bytes = params[1]; // # of bytes to read from each servo
int k = 2;
checksum = id + (bytes*(length-4)) + 2;
Serial.print(0xff);
Serial.print(0xff);
Serial.print(id);
Serial.print(2+(bytes*(length-4)));
Serial.print(0); // error code
// send actual data
for(k=2; k<length-2; k++){
if( ax12GetRegister(params[k], start, bytes) >= 0){
for(i=0;i<bytes;i++){
checksum += ax_rx_buffer[5+i];
Serial.print(ax_rx_buffer[5+i]);
}
}else{
for(i=0;i<bytes;i++){
checksum += 255;
Serial.print(255);
}
}
}
Serial.print(255-((checksum)%256));
}else{
// TODO: sync write pass thru
int k;
setTXall();
ax12write(0xff);
ax12write(0xff);
ax12write(id);
ax12write(length);
ax12write(ins);
for(k=0; k<length; k++)
ax12write(params[k]);
// no return
}
}else{ // ID != 253, pass thru
switch(ins){
// TODO: streamline this
case AX_READ_DATA:
ax12GetRegister(id, params[0], params[1]);
// return a packet: FF FF id Len Err params check
if(ax_rx_buffer[3] > 0){
for(i=0;i<ax_rx_buffer[3]+4;i++)
Serial.print(ax_rx_buffer[i]);
}
ax_rx_buffer[3] = 0;
break;

case AX_WRITE_DATA:
if(length == 4){
ax12SetRegister(id, params[0], params[1]);
}else{
int x = params[1] + (params[2]<<8);
ax12SetRegister2(id, params[0], x);
}
statusPacket(id,0);
break;

}
}
}
} // end mode == 5
} // end while(available)
// update joints
for(int i=0; i<5; i++)
controllers[i].interpolateStep();

#ifdef USE_BASE
// update pid
updatePID();
#endif

}

I have been following PiRobots tutorial [I]ROS by Example: Head Tracking using OpenCV. This was EXTREMELY helpful and got moving moving ahead nicely (Thanks Patrick!).

I am currently stuck on getting the servos and arbotix to function.

What I am hoping someone can start with is helping me to download the right Trunk or tag version for ROS Fuerte (I think it is .6.1). The correct firmware for the arbotix controller. Finally, the correct libraries to be included in the Arduino install.

When I tried to follow the driections on 4 different sites, it had me copying files from 2011, then copying in things over the 2011 stuff from 2010. Not to mention several things that were just becoming confusing.

I am hoping that once I have the correct files, that I can plod forward a bit more before before seeking any more help...

Thanks for any help available!

Matthew

lnxfergy
07-17-2012, 05:53 AM
Matthew,

Our releases are a bit behind (I've been distracted lately by the day job). For using with ROS Fuerte, I would recommend using trunk of both the arbotix firmware and the vanadium-ros-pkg repos and Arduino 1.0. I have been successfully using trunk on my robot, Maxwell, for some time, but haven't managed to get a new release out (which I actually promised to Patrick several weeks ago....).

You'll find the libraries and hardware folders here: http://arbotix.googlecode.com/svn/trunk/
And the ROS nodes here: http://vanadium-ros-pkg.googlecode.com/svn/trunk/arbotix/
The actual ros.ino will be found inside http://vanadium-ros-pkg.googlecode.com/svn/trunk/arbotix/arbotix_firmware

-Fergs

MatthewGP
07-17-2012, 10:08 AM
Fergs,

Thanks for the response. I will pull everything from trunk and then compile a list of things if adjustments need to be made or I encounter issues. That way there will be a list somewhere in case any one else encounters the same things.

I totally understand the day job! That thing gets into the way of my hobbies more than it should be allowed to :rolleyes:.

Matthew

lnxfergy
07-17-2012, 11:53 PM
Fergs,

Thanks for the response. I will pull everything from trunk and then compile a list of things if adjustments need to be made or I encounter issues. That way there will be a list somewhere in case any one else encounters the same things.

I totally understand the day job! That thing gets into the way of my hobbies more than it should be allowed to :rolleyes:.

Matthew

As far as I know, it should compile out of the box -- if it doesn't, we have some sort of bug that cropped up, and please do post it here so we can fix it.

-Fergs

Pi Robot
08-09-2012, 11:24 AM
Matthew,

Our releases are a bit behind (I've been distracted lately by the day job). For using with ROS Fuerte, I would recommend using trunk of both the arbotix firmware and the vanadium-ros-pkg repos and Arduino 1.0. I have been successfully using trunk on my robot, Maxwell, for some time, but haven't managed to get a new release out (which I actually promised to Patrick several weeks ago....).

You'll find the libraries and hardware folders here: http://arbotix.googlecode.com/svn/trunk/
And the ROS nodes here: http://vanadium-ros-pkg.googlecode.com/svn/trunk/arbotix/
The actual ros.ino will be found inside http://vanadium-ros-pkg.googlecode.com/svn/trunk/arbotix/arbotix_firmware

-Fergs

Hey Fergs,

I just put together a shiny new PhantomX Turret with AX-12s and the ArbotiX that comes with it. The ROS firmware loaded fine and everything works as advertised if I use the ROS Electric Debian packages for the arbotix stack (Ubuntu 11.10). However, if I use the trunk version (which I need for the odometry fix you applied a few weeks back), I get the following error on startup:


[ERROR] [WallTime: 1344529206.678543] Unrecognized controller: follow_controller

My YAML file looks like this:


port: /dev/ttyUSB0
baud: 115200
rate: 20
sync_write: True
sync_read: True
read_rate: 20
write_rate: 20


dynamixels: {
head_pan_joint: {id: 1, neutral: 512, max_speed: 100, min_angle: -145, max_angle: 145, invert: False},
head_tilt_joint: {id: 2, neutral: 512, max_speed: 100, min_angle: -90, max_angle: 90, invert: False}
}


controllers: {
head_controller: {type: follow_controller, joints: [head_pan_joint, head_tilt_joint], action_name: head_controller/follow_joint_trajectory, onboard: False }
}


As I say, this works fine with the Electric Debian version of the arbotix_python controllers.

--patrick

lnxfergy
08-10-2012, 01:01 AM
Patrick,

I haven't been able to reproduce this -- I have pushed a quick patch that should give us a more verbose error message, please pull, re-run and post the output.

Thanks,
-Fergs

Pi Robot
08-10-2012, 08:29 AM
Patrick,

I haven't been able to reproduce this -- I have pushed a quick patch that should give us a more verbose error message, please pull, re-run and post the output.

Thanks,
-Fergs

Thanks Fergs,

Took me forever to figure it out--the KeyError was actually coming from inside follow_controller.py due to the fact that my servo dictionary was called "dynamixels" in my YAML file instead of "joints". I think perhaps that was an API change at some point that I forgot about? (I was using an older YAML file.)

Anyway, problem solved.

--patrick

Pi Robot
08-12-2012, 10:11 PM
Hi Fergs,

It looks like you made a tweak to arbotix_python in trunk a couple of days ago (r803 - "revert removal of dynamixels/servos dictionaries, note tick-tock") and now I am getting the following error on launch:


[INFO] [WallTime: 1344827166.025388] ArbotiX being simulated.
[WARN] [WallTime: 1344827166.033948] Warning: use of dynamixels as a dictionary is deprecated and will be removed in 0.8.0
Traceback (most recent call last):
File "/home/patrick/ros_workspace/arbotix/arbotix_python/nodes/driver.py", line 187, in <module>
a = ArbotixROS()
File "/home/patrick/ros_workspace/arbotix/arbotix_python/nodes/driver.py", line 85, in __init__
self.joints[name] = DynamixelServo(self, name, "~dynamixels")
AttributeError: ArbotixROS instance has no attribute 'joints'

--patrick

Pi Robot
08-12-2012, 10:18 PM
Arghhh. My bad again. I had an old ~dynamixels parameter lying around on the Parameter server from an earlier launch. Sorry.

--patrick

lnxfergy
08-12-2012, 10:51 PM
Patrick,

I just committed another patch -- I had tested against new parameters, but never tested against old-style parameters when I brought back the old style for compatibilty.

-Fergs

P.S. I'm still traveling at the moment, but I intend to get a new debian release of arbotix into both electric and fuerte this week, and then update the wiki as soon as the changes propagate to public-facing debs.

Pi Robot
08-13-2012, 10:51 AM
Thanks Fergs! And good to hear that the Debs will be coming soon. Thanks especially for working on the patches while you are traveling!

--patrick