Question

I'm using Player/Stage SWIG generated code from C and now I'm trying to access a structure where a value points to another structure. I wonder how I can extract the array of structures in python.

The C code looks like this:

/** @brief Localization device data. */
typedef struct
{
  /** Device info; must be at the start of all device structures. */
  playerc_device_t info;

  /** Map dimensions (cells). */
  int map_size_x, map_size_y;

  /** Map scale (m/cell). */
  double map_scale;

  /** Next map tile to read. */
  int map_tile_x, map_tile_y;

  /** Map data (empty = -1, unknown = 0, occupied = +1). */
  int8_t *map_cells;

  /** The number of pending (unprocessed) sensor readings. */
  int pending_count;

  /** The timestamp on the last reading processed. */
  double pending_time;

  /** List of possible poses. */
  int hypoth_count;
  player_localize_hypoth_t *hypoths;

  double mean[3];
  double variance;
  int num_particles;
  playerc_localize_particle_t *particles;

} playerc_localize_t;

/** @brief Hypothesis format.

Since the robot pose may be ambiguous (i.e., the robot may at any
of a number of widely spaced locations), the @p localize interface is
capable of returning more that one hypothesis. */
typedef struct player_localize_hypoth
{
  /** The mean value of the pose estimate (m, m, rad). */
  player_pose2d_t mean;
  /** The covariance matrix pose estimate (lower half, symmetric matrix) 
      (cov(xx) in m$^2$, cov(yy) in $^2$, cov(aa) in rad$^2$, 
       cov(xy), cov(ya), cov(xa) ). */
  double cov[6];
  /** The weight coefficient for linear combination (alpha) */
  double alpha;
} player_localize_hypoth_t;

The code for python is automatically generated. I'm trying to access the elements in hypoths variable, how can I do this in python? I can access most of the variables. Below is the generated swig code...

class playerc_localize(_object):
    __swig_setmethods__ = {}
    __setattr__ = lambda self, name, value: _swig_setattr(self, playerc_localize, name, value)
    __swig_getmethods__ = {}
    __getattr__ = lambda self, name: _swig_getattr(self, playerc_localize, name)
    __repr__ = _swig_repr
    __swig_setmethods__["info"] = _playerc.playerc_localize_info_set
    __swig_getmethods__["info"] = _playerc.playerc_localize_info_get
    if _newclass:info = _swig_property(_playerc.playerc_localize_info_get, _playerc.playerc_localize_info_set)
    __swig_setmethods__["map_size_x"] = _playerc.playerc_localize_map_size_x_set
    __swig_getmethods__["map_size_x"] = _playerc.playerc_localize_map_size_x_get
    if _newclass:map_size_x = _swig_property(_playerc.playerc_localize_map_size_x_get, _playerc.playerc_localize_map_size_x_set)
    __swig_setmethods__["map_size_y"] = _playerc.playerc_localize_map_size_y_set
    __swig_getmethods__["map_size_y"] = _playerc.playerc_localize_map_size_y_get
    if _newclass:map_size_y = _swig_property(_playerc.playerc_localize_map_size_y_get, _playerc.playerc_localize_map_size_y_set)
    __swig_setmethods__["map_scale"] = _playerc.playerc_localize_map_scale_set
    __swig_getmethods__["map_scale"] = _playerc.playerc_localize_map_scale_get
    if _newclass:map_scale = _swig_property(_playerc.playerc_localize_map_scale_get, _playerc.playerc_localize_map_scale_set)
    __swig_setmethods__["map_tile_x"] = _playerc.playerc_localize_map_tile_x_set
    __swig_getmethods__["map_tile_x"] = _playerc.playerc_localize_map_tile_x_get
    if _newclass:map_tile_x = _swig_property(_playerc.playerc_localize_map_tile_x_get, _playerc.playerc_localize_map_tile_x_set)
    __swig_setmethods__["map_tile_y"] = _playerc.playerc_localize_map_tile_y_set
    __swig_getmethods__["map_tile_y"] = _playerc.playerc_localize_map_tile_y_get
    if _newclass:map_tile_y = _swig_property(_playerc.playerc_localize_map_tile_y_get, _playerc.playerc_localize_map_tile_y_set)
    __swig_setmethods__["map_cells"] = _playerc.playerc_localize_map_cells_set
    __swig_getmethods__["map_cells"] = _playerc.playerc_localize_map_cells_get
    if _newclass:map_cells = _swig_property(_playerc.playerc_localize_map_cells_get, _playerc.playerc_localize_map_cells_set)
    __swig_setmethods__["pending_count"] = _playerc.playerc_localize_pending_count_set
    __swig_getmethods__["pending_count"] = _playerc.playerc_localize_pending_count_get
    if _newclass:pending_count = _swig_property(_playerc.playerc_localize_pending_count_get, _playerc.playerc_localize_pending_count_set)
    __swig_setmethods__["pending_time"] = _playerc.playerc_localize_pending_time_set
    __swig_getmethods__["pending_time"] = _playerc.playerc_localize_pending_time_get
    if _newclass:pending_time = _swig_property(_playerc.playerc_localize_pending_time_get, _playerc.playerc_localize_pending_time_set)
    __swig_setmethods__["hypoth_count"] = _playerc.playerc_localize_hypoth_count_set
    __swig_getmethods__["hypoth_count"] = _playerc.playerc_localize_hypoth_count_get
    if _newclass:hypoth_count = _swig_property(_playerc.playerc_localize_hypoth_count_get, _playerc.playerc_localize_hypoth_count_set)
    __swig_setmethods__["hypoths"] = _playerc.playerc_localize_hypoths_set
    __swig_getmethods__["hypoths"] = _playerc.playerc_localize_hypoths_get
    if _newclass:hypoths = _swig_property(_playerc.playerc_localize_hypoths_get, _playerc.playerc_localize_hypoths_set)
    __swig_setmethods__["mean"] = _playerc.playerc_localize_mean_set
    __swig_getmethods__["mean"] = _playerc.playerc_localize_mean_get
    if _newclass:mean = _swig_property(_playerc.playerc_localize_mean_get, _playerc.playerc_localize_mean_set)
    __swig_setmethods__["variance"] = _playerc.playerc_localize_variance_set
    __swig_getmethods__["variance"] = _playerc.playerc_localize_variance_get
    if _newclass:variance = _swig_property(_playerc.playerc_localize_variance_get, _playerc.playerc_localize_variance_set)
    __swig_setmethods__["num_particles"] = _playerc.playerc_localize_num_particles_set
    __swig_getmethods__["num_particles"] = _playerc.playerc_localize_num_particles_get
    if _newclass:num_particles = _swig_property(_playerc.playerc_localize_num_particles_get, _playerc.playerc_localize_num_particles_set)
    __swig_setmethods__["particles"] = _playerc.playerc_localize_particles_set
    __swig_getmethods__["particles"] = _playerc.playerc_localize_particles_get
    if _newclass:particles = _swig_property(_playerc.playerc_localize_particles_get, _playerc.playerc_localize_particles_set)
    def __init__(self, *args): 
        this = _playerc.new_playerc_localize(*args)
        try: self.this.append(this)
        except: self.this = this
    def destroy(self): return _playerc.playerc_localize_destroy(self)
    def subscribe(self, *args): return _playerc.playerc_localize_subscribe(self, *args)
    def unsubscribe(self): return _playerc.playerc_localize_unsubscribe(self)
    def set_pose(self, *args): return _playerc.playerc_localize_set_pose(self, *args)
    def get_particles(self): return _playerc.playerc_localize_get_particles(self)
    __swig_destroy__ = _playerc.delete_playerc_localize
    __del__ = lambda self : None;
playerc_localize_swigregister = _playerc.playerc_localize_swigregister
playerc_localize_swigregister(playerc_localize)

Everything compiles in SWIG, but now my python code gives errors. I know that the alpha line may be wrong, but I get the same error for both lines:

LOC = playerc_localize(CON, 0)
if LOC.subscribe(PLAYERC_OPEN_MODE) != 0:
   raise playerc_error_str()

CON.read()
# This should work right? If I omit the index,
# then I get the first value from the array.
print LOC.get_hypoth(0).alpha
print LOC.get_hypoth(1)

I get the following errors in python:

print LOC.get_hypoth(1).alpha
File "/usr/local/lib/python2.7/dist-packages/playerc.py", line 7413, in get_hypoth
return _playerc._playerc_localize_get_hypoth(self, index)
TypeError: in method '_playerc_localize_get_hypoth', argument 1 of type 'playerc_localize_t *'

PART II I've come around another problem, again I'm trying to access some values but it doesn't work and I can't figure out whats wrong. I'm trying to access waypoints in the planner device:

PLN = playerc_planner(CON, 0)
  if PLN.subscribe(PLAYERC_OPEN_MODE) != 0:
     raise playerc_error_str()
# saves the waypoints in PLN.waypoints
PLN.get_waypoints()
# gives: <Swig Object of type 'double (*)[3]' at 0x38105d0>
# if i try accessing members of it using (0) or [0] or something I get errors
print PLN.waypoints

Now the related files and parts: in playerc.py

class playerc_planner(_object):
...
__swig_setmethods__["waypoints"] = _playerc.playerc_planner_waypoints_set
    __swig_getmethods__["waypoints"] = _playerc.playerc_planner_waypoints_get
    if _newclass:waypoints = _swig_property(_playerc.playerc_planner_waypoints_get, _playerc.playerc_planner_waypoints_set)

The part in playerc_wrap.i:

%header
%{
    #define new_playerc_planner playerc_planner_create
    #define del_playerc_planner playerc_planner_destroy
    typedef playerc_planner_t playerc_planner;
%}

typedef struct
{
  playerc_device info;
  int path_valid;
  int path_done;
  double px, py, pa;
  double gx, gy, ga;
  double wx, wy, wa;
  int curr_waypoint;
  int waypoint_count;
  double (*waypoints)[3];
    %extend
    {
        playerc_planner (playerc_client *client, int index);
        void destroy(void);
        int subscribe (int access);
        int unsubscribe (void);
        int set_cmd_pose (double gx, double gy, double ga);
        int get_waypoints (void);
        int enable (int state);
    }
} playerc_planner;

And the related part in playerc_wrap.h:

typedef struct
{
  playerc_device_t info;
  int path_valid;
  int path_done;
  double px, py, pa;
  double gx, gy, ga;
  double wx, wy, wa;
  int curr_waypoint;
  int waypoint_count;
  double (*waypoints)[3];
} playerc_planner_t;

PLAYERC_EXPORT playerc_planner_t *playerc_planner_create(playerc_client_t *client, int index);
PLAYERC_EXPORT void playerc_planner_destroy(playerc_planner_t *device);
PLAYERC_EXPORT int playerc_planner_subscribe(playerc_planner_t *device, int access);
PLAYERC_EXPORT int playerc_planner_unsubscribe(playerc_planner_t *device);
PLAYERC_EXPORT int playerc_planner_set_cmd_pose(playerc_planner_t *device,
                                  double gx, double gy, double ga);
PLAYERC_EXPORT int playerc_planner_get_waypoints(playerc_planner_t *device);

PLAYERC_EXPORT int playerc_planner_enable(playerc_planner_t *device, int state);

So I'm again lost in how to access the waypoints in this double(*)[3] variable, I tried some stuff but it all fails to compile in SWIG. Again thanks!

Was it helpful?

Solution

It looks like those dynamically sized arrays are not properly wrapped in libcplayer's SWIG interface file. The LOC.hypoths accessor will probably just give you the first element in the array, not any of the others.

I think the easiest thing to do would be to add something like this to playerc.i and regenerate the SWIG bindings:

%inline %{
  player_localize_hypoth_t *_playerc_localize_get_hypoth(playerc_localize *localize, int index)
  {
    return &(localize->hypoths[index]);
  }
%}

%extend playerc_localize {
  %pythoncode %{
    def get_hypoth(self, index):
        return _playerc._playerc_localize_get_hypoth(self, index)
  %}
}

Then you should be able to access element number n in Python with LOC.get_hypoth(n).

References:

Notes:

The name of the struct is playerc_localize instead of playerc_localize_t because of the regular expressions applied to the interface file by the playerc_swig_parse.py script.

Part II

A similar problem. Again, there might be a cleverer way to do this, but this simple way is nice and clean and there's no need to try and make it any more complicated than it already is:

%inline %{
  double _playerc_planner_get_waypoint_coord(playerc_planner *planner, int index, int coord)
  {
    return planner->waypoints[index][coord];
  }
%}

%extend playerc_planner {
  %pythoncode %{
    def get_waypoint(self, index):
        x = _playerc._playerc_planner_get_waypoint_coord(self, index, 0)
        y = _playerc._playerc_planner_get_waypoint_coord(self, index, 1)
        z = _playerc._playerc_planner_get_waypoint_coord(self, index, 2)
        return (x, y, z)
  %}
}

Then you should be able to access waypoint number n in Python like this:

(x, y, z) = PLN.get_waypoint(n)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top